home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / comm2 / termsorc.lha / Extras / Source / term-source.lha / termTextBuffer.c < prev    next >
C/C++ Source or Header  |  1995-09-26  |  74KB  |  2,947 lines

  1. /*
  2. **    termTextBuffer.c
  3. **
  4. **    Support routines for the text buffer.
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #include "termGlobal.h"
  13.  
  14.     /* Gadget ID codes. */
  15.  
  16. enum    {    GAD_SCROLLER,GAD_UP,GAD_DOWN };
  17.  
  18.     /* Menu ID codes. */
  19.  
  20. enum    {    MEN_SEARCH,MEN_REPEAT,MEN_GOTO,MEN_CLEARBUF_CONTENTS,MEN_QUITBUF,MEN_PASTECLIP };
  21.  
  22.     /* A handy macro to determine the length of a string. */
  23.  
  24. #define LINE_WIDTH(s)    (s)[-1]
  25.  
  26.     /* Some private data (render info & window). */
  27.  
  28. typedef struct TextBufferInfo
  29. {
  30.     UWORD                 Left,Top,
  31.                          Width,Height;
  32.  
  33.     struct Process        *Buddy;
  34.  
  35.     struct Window        *Window;
  36.     struct Screen        *Screen;
  37.     struct Menu            *BufferMenuStrip;
  38.  
  39.     BYTE                 BufferSignal;
  40.     BOOLEAN                 BufferTerminated;
  41.  
  42.     struct RastPort        *RPort;
  43.  
  44.     LONG                 NumBufferLines,
  45.                          NumBufferColumns,
  46.                          LastTopLine;
  47.  
  48.     struct DrawInfo        *BufferDrawInfo;
  49.     struct Image        *BufferAmigaGlyph,
  50.                         *BufferCheckGlyph;
  51.  
  52.     struct TextFont        *LocalFont;
  53.  
  54.     WORD                 LocalTextFontWidth,
  55.                          LocalTextFontHeight,
  56.                          LocalTextFontBase;
  57.  
  58.     struct TTextAttr     LocalTextFont;
  59.     UBYTE                 LocalTextFontName[MAX_FILENAME_LENGTH];
  60.  
  61.     struct TTextAttr     LocalUserFont;
  62.     UBYTE                 LocalUserFontName[MAX_FILENAME_LENGTH];
  63.  
  64.     LONG                 TopLine,
  65.                          DisplayedLines;
  66.  
  67.     BOOLEAN                 SearchForward,
  68.                          IgnoreCase,
  69.                          WholeWords,
  70.                          NeedClipConversion;
  71.  
  72.     struct Gadget        *Scroller,
  73.                         *UpArrow,
  74.                         *DownArrow;
  75.  
  76.     struct Image        *UpImage,
  77.                         *DownImage;
  78.  
  79.     UWORD                *BufferLineWidths,
  80.                         *BufferLineOffsets,
  81.                         *BufferColumnOffsets;
  82.  
  83.     ULONG                 ArrowWidth,
  84.                          ArrowHeight;
  85.  
  86.     UWORD                 TitleFrontPen,
  87.                          TitleBackPen,
  88.                          TextFrontPen,
  89.                          TextBackPen;
  90.  
  91.     WORD                 OldColumn,
  92.                          OldLine,
  93.                          OldLength;
  94.  
  95.     LONG                 TitleOffset;
  96.     LONG                 MaxPen;
  97.     WORD                 RightBorderWidth;
  98.  
  99.     struct Screen        *Parent;
  100.  
  101.     UBYTE                 TitleBuffer[100];
  102.  
  103.     struct MsgQueue        *Queue;
  104.     ULONG                 QueueMask;
  105.  
  106.     BOOLEAN                *pSearchForward;
  107.     BOOLEAN                *pIgnoreCase;
  108.     BOOLEAN                *pWholeWords;
  109.     LONG                *pTopLine;
  110. } TextBufferInfo;
  111.  
  112. STATIC VOID __regargs
  113. BufferClear(TextBufferInfo *BufferInfo,WORD Left,WORD Top,WORD Right,WORD Bottom)
  114. {
  115.     struct RastPort    *RPort = BufferInfo -> RPort;
  116.  
  117.     Left    += BufferInfo -> Left;
  118.     Top        += BufferInfo -> Top;
  119.     Right    += BufferInfo -> Left;
  120.     Bottom    += BufferInfo -> Top;
  121.  
  122.     if(Right >= BufferInfo -> Left + BufferInfo -> Width)
  123.         Right = BufferInfo -> Left + BufferInfo -> Width - 1;
  124.  
  125.     if(Bottom >= BufferInfo -> Top + BufferInfo -> Height)
  126.         Bottom = BufferInfo -> Top + BufferInfo -> Height - 1;
  127.  
  128.     if(Left <= Right && Top <= Bottom)
  129.     {
  130.         SetAPen(RPort,BufferInfo -> TextBackPen);
  131.         RectFill(RPort,Left,Top,Right,Bottom);
  132.         SetAPen(RPort,BufferInfo -> TextFrontPen);
  133.     }
  134. }
  135.  
  136. STATIC VOID __regargs
  137. BufferText(TextBufferInfo *BufferInfo,WORD Left,WORD Top,STRPTR Buffer,WORD Len)
  138. {
  139.     struct RastPort *RPort = BufferInfo -> RPort;
  140.  
  141.     Move(RPort,BufferInfo -> Left + Left,BufferInfo -> Top + Top);
  142.     Text(RPort,Buffer,Len);
  143. }
  144.  
  145. STATIC VOID __regargs
  146. BufferScroll(TextBufferInfo *BufferInfo,LONG Lines)
  147. {
  148.     if(Lines < 0)
  149.         Lines = -BufferInfo -> BufferLineOffsets[-Lines];
  150.     else
  151.         Lines = BufferInfo -> BufferLineOffsets[Lines];
  152.  
  153.     ScrollRaster(BufferInfo -> RPort,0,Lines,BufferInfo -> Left,BufferInfo -> Top,BufferInfo -> Left + BufferInfo -> Width - 1,BufferInfo -> Top + BufferInfo -> Height - 1);
  154. }
  155.  
  156. STATIC VOID __regargs
  157. BufferComplement(TextBufferInfo *BufferInfo,WORD SrcX,WORD SrcY,WORD Width,WORD Height)
  158. {
  159.     struct RastPort *RPort = BufferInfo -> RPort;
  160.  
  161.     if(Kick30)
  162.     {
  163.         SetMaxPen(RPort,(ULONG)~0);
  164.         SetABPenDrMd(RPort,(ULONG)~0,0,JAM1 | COMPLEMENT);
  165.     }
  166.     else
  167.     {
  168.         SetAPen(RPort,(ULONG)~0);
  169.         SetDrMd(RPort,JAM1 | COMPLEMENT);
  170.     }
  171.  
  172.     SrcX    += BufferInfo -> Left;
  173.     SrcY    += BufferInfo -> Top;
  174.  
  175.     RectFill(RPort,SrcX,SrcY,SrcX + Width - 1,SrcY + Height - 1);
  176.  
  177.     if(Kick30)
  178.     {
  179.         SetABPenDrMd(RPort,BufferInfo -> TextFrontPen,BufferInfo -> TextBackPen,JAM2);
  180.         SetMaxPen(RPort,BufferInfo -> MaxPen);
  181.     }
  182.     else
  183.     {
  184.         SetAPen(RPort,BufferInfo -> TextFrontPen);
  185.         SetDrMd(RPort,JAM2);
  186.     }
  187. }
  188.  
  189.     /* DeleteScroller(VOID):
  190.      *
  191.      *    Delete scroller and arrow objects.
  192.      */
  193.  
  194. STATIC VOID __regargs
  195. DeleteScroller(TextBufferInfo *BufferInfo)
  196. {
  197.     if(BufferInfo -> Scroller)
  198.         DisposeObject(BufferInfo -> Scroller);
  199.  
  200.     if(BufferInfo -> UpArrow)
  201.         DisposeObject(BufferInfo -> UpArrow);
  202.  
  203.     if(BufferInfo -> DownArrow)
  204.         DisposeObject(BufferInfo -> DownArrow);
  205.  
  206.     if(BufferInfo -> UpImage)
  207.         DisposeObject(BufferInfo -> UpImage);
  208.  
  209.     if(BufferInfo -> DownImage)
  210.         DisposeObject(BufferInfo -> DownImage);
  211. }
  212.  
  213.     /* CreateScroller(LONG Height):
  214.      *
  215.      *    Create scroller and arrow objects.
  216.      */
  217.  
  218. STATIC BOOLEAN __regargs
  219. CreateScroller(TextBufferInfo *BufferInfo,LONG Height)
  220. {
  221.     STATIC struct TagItem ArrowMappings[] = { GA_ID,GA_ID,TAG_END };
  222.  
  223.     BOOLEAN             Result = FALSE;
  224.     UWORD             SizeType;
  225.     struct Screen    *Screen;
  226.  
  227.     if(BufferInfo -> Parent)
  228.         Screen = BufferInfo -> Parent;
  229.     else
  230.         Screen = BufferInfo -> Screen;
  231.  
  232.     if(Screen -> Flags & SCREENHIRES)
  233.         SizeType = SYSISIZE_MEDRES;
  234.     else
  235.         SizeType = SYSISIZE_LOWRES;
  236.  
  237.     if(!BufferInfo -> Parent)
  238.     {
  239.         if(BufferInfo -> UpImage = (struct Image *)NewObject(NULL,SYSICLASS,
  240.             SYSIA_Size,        SizeType,
  241.             SYSIA_Which,    UPIMAGE,
  242.             SYSIA_DrawInfo,    BufferInfo -> BufferDrawInfo,
  243.         TAG_DONE))
  244.         {
  245.             if(BufferInfo -> DownImage = (struct Image *)NewObject(NULL,SYSICLASS,
  246.                 SYSIA_Size,        SizeType,
  247.                 SYSIA_Which,    DOWNIMAGE,
  248.                 SYSIA_DrawInfo,    BufferInfo -> BufferDrawInfo,
  249.             TAG_DONE))
  250.             {
  251.                 LONG ScrollerHeight,LeftEdge;
  252.  
  253.                 GetAttr(IA_Height,    BufferInfo -> UpImage,&BufferInfo -> ArrowHeight);
  254.                 GetAttr(IA_Width,    BufferInfo -> UpImage,&BufferInfo -> ArrowWidth);
  255.  
  256.                 ScrollerHeight = Height - 2 * BufferInfo -> ArrowHeight;
  257.  
  258.                 LeftEdge = BufferInfo -> Screen -> Width - BufferInfo -> ArrowWidth;
  259.  
  260.                 if(BufferInfo -> Scroller = NewObject(NULL,PROPGCLASS,
  261.                     GA_ID,            GAD_SCROLLER,
  262.  
  263.                     GA_Top,            0,
  264.                     GA_Left,        LeftEdge,
  265.                     GA_Width,        BufferInfo -> ArrowWidth,
  266.                     GA_Height,        ScrollerHeight,
  267.                     GA_Immediate,    TRUE,
  268.                     GA_FollowMouse,    TRUE,
  269.                     GA_RelVerify,    TRUE,
  270.  
  271.                     PGA_Freedom,    FREEVERT,
  272.                     PGA_NewLook,    TRUE,
  273.  
  274.                     PGA_Visible,    1,
  275.                     PGA_Total,        1,
  276.                 TAG_DONE))
  277.                 {
  278.                     if(BufferInfo -> UpArrow = NewObject(NULL,BUTTONGCLASS,
  279.                         GA_ID,            GAD_UP,
  280.                         GA_Image,        BufferInfo -> UpImage,
  281.                         GA_Left,        LeftEdge,
  282.                         GA_Top,            ScrollerHeight,
  283.                         GA_Height,        BufferInfo -> ArrowHeight,
  284.                         GA_Width,        BufferInfo -> ArrowWidth,
  285.                         GA_Immediate,    TRUE,
  286.                         GA_RelVerify,    TRUE,
  287.                         GA_Previous,    BufferInfo -> Scroller,
  288.  
  289.                         ICA_TARGET,        ICTARGET_IDCMP,
  290.                         ICA_MAP,        ArrowMappings,
  291.                     TAG_DONE))
  292.                     {
  293.                         if(BufferInfo -> DownArrow = NewObject(NULL,BUTTONGCLASS,
  294.                             GA_ID,            GAD_DOWN,
  295.                             GA_Image,        BufferInfo -> DownImage,
  296.                             GA_Left,        LeftEdge,
  297.                             GA_Top,            ScrollerHeight + BufferInfo -> ArrowHeight,
  298.                             GA_Height,        BufferInfo -> ArrowHeight,
  299.                             GA_Width,        BufferInfo -> ArrowWidth,
  300.                             GA_Immediate,    TRUE,
  301.                             GA_RelVerify,    TRUE,
  302.                             GA_Previous,    BufferInfo -> UpArrow,
  303.  
  304.                             ICA_TARGET,        ICTARGET_IDCMP,
  305.                             ICA_MAP,        ArrowMappings,
  306.                         TAG_DONE))
  307.                             Result = TRUE;
  308.                     }
  309.                 }
  310.             }
  311.         }
  312.     }
  313.     else
  314.     {
  315.         struct Image *SizeImage;
  316.  
  317.         if(SizeImage = (struct Image *)NewObject(NULL,SYSICLASS,
  318.             SYSIA_Size,        SizeType,
  319.             SYSIA_Which,    SIZEIMAGE,
  320.             SYSIA_DrawInfo,    BufferInfo -> BufferDrawInfo,
  321.         TAG_DONE))
  322.         {
  323.             ULONG SizeWidth,SizeHeight;
  324.  
  325.             GetAttr(IA_Width,    SizeImage,&SizeWidth);
  326.             GetAttr(IA_Height,    SizeImage,&SizeHeight);
  327.  
  328.             DisposeObject(SizeImage);
  329.  
  330.             BufferInfo -> RightBorderWidth = SizeWidth;
  331.  
  332.             if(BufferInfo -> UpImage = (struct Image *)NewObject(NULL,SYSICLASS,
  333.                 SYSIA_Size,        SizeType,
  334.                 SYSIA_Which,    UPIMAGE,
  335.                 SYSIA_DrawInfo,    BufferInfo -> BufferDrawInfo,
  336.             TAG_DONE))
  337.             {
  338.                 GetAttr(IA_Height,BufferInfo -> UpImage,&BufferInfo -> ArrowHeight);
  339.  
  340.                 if(BufferInfo -> DownImage = (struct Image *)NewObject(NULL,SYSICLASS,
  341.                     SYSIA_Size,        SizeType,
  342.                     SYSIA_Which,    DOWNIMAGE,
  343.                     SYSIA_DrawInfo,    BufferInfo -> BufferDrawInfo,
  344.                 TAG_DONE))
  345.                 {
  346.                     if(BufferInfo -> Scroller = NewObject(NULL,PROPGCLASS,
  347.                         GA_ID,            GAD_SCROLLER,
  348.  
  349.                         GA_Top,            Screen -> WBorTop + Screen -> Font -> ta_YSize + 2,
  350.                         GA_RelHeight,    -(Screen -> WBorTop + Screen -> Font -> ta_YSize + 2 + SizeHeight + 1 + 2 * BufferInfo -> ArrowHeight),
  351.                         GA_Width,        SizeWidth - 8,
  352.                         GA_RelRight,    -(SizeWidth - 5),
  353.  
  354.                         GA_Immediate,    TRUE,
  355.                         GA_FollowMouse,    TRUE,
  356.                         GA_RelVerify,    TRUE,
  357.                         GA_RightBorder,    TRUE,
  358.  
  359.                         PGA_Freedom,    FREEVERT,
  360.                         PGA_NewLook,    TRUE,
  361.                         PGA_Borderless,    TRUE,
  362.  
  363.                         PGA_Visible,    1,
  364.                         PGA_Total,        1,
  365.                     TAG_DONE))
  366.                     {
  367.                         if(BufferInfo -> UpArrow = NewObject(NULL,BUTTONGCLASS,
  368.                             GA_ID,            GAD_UP,
  369.  
  370.                             GA_Image,        BufferInfo -> UpImage,
  371.                             GA_RelRight,    -(SizeWidth - 1),
  372.                             GA_RelBottom,    -(SizeHeight - 1 + 2 * BufferInfo -> ArrowHeight),
  373.                             GA_Height,        BufferInfo -> ArrowHeight,
  374.                             GA_Width,        SizeWidth,
  375.                             GA_Immediate,    TRUE,
  376.                             GA_RelVerify,    TRUE,
  377.                             GA_Previous,    BufferInfo -> Scroller,
  378.                             GA_RightBorder,    TRUE,
  379.  
  380.                             ICA_TARGET,        ICTARGET_IDCMP,
  381.                             ICA_MAP,        ArrowMappings,
  382.                         TAG_DONE))
  383.                         {
  384.                             if(BufferInfo -> DownArrow = NewObject(NULL,BUTTONGCLASS,
  385.                                 GA_ID,            GAD_DOWN,
  386.  
  387.                                 GA_Image,        BufferInfo -> DownImage,
  388.                                 GA_RelRight,    -(SizeWidth - 1),
  389.                                 GA_RelBottom,    -(SizeHeight - 1 + BufferInfo -> ArrowHeight),
  390.                                 GA_Height,        BufferInfo -> ArrowHeight,
  391.                                 GA_Width,        SizeWidth,
  392.                                 GA_Immediate,    TRUE,
  393.                                 GA_RelVerify,    TRUE,
  394.                                 GA_Previous,    BufferInfo -> UpArrow,
  395.                                 GA_RightBorder,    TRUE,
  396.  
  397.                                 ICA_TARGET,        ICTARGET_IDCMP,
  398.                                 ICA_MAP,        ArrowMappings,
  399.                             TAG_DONE))
  400.                                 Result = TRUE;
  401.                         }
  402.                     }
  403.                 }
  404.             }
  405.         }
  406.     }
  407.  
  408.     if(!Result)
  409.         DeleteScroller(BufferInfo);
  410.  
  411.     return(Result);
  412. }
  413.  
  414.     /* PrintLine(STRPTR Buffer,LONG LineNumber):
  415.      *
  416.      *    Print a line at a given line number in the displayed area.
  417.      */
  418.  
  419. STATIC VOID __regargs
  420. PrintLine(TextBufferInfo *BufferInfo,STRPTR Buffer,LONG LineNumber)
  421. {
  422.     WORD Length = Buffer[-1];
  423.  
  424.         /* Print the text. */
  425.  
  426.     if(Length > 0)
  427.     {
  428.         if(Length > BufferInfo -> NumBufferColumns)
  429.             Length = BufferInfo -> NumBufferColumns;
  430.  
  431.         if(Length > 0)
  432.             BufferText(BufferInfo,0,BufferInfo -> BufferLineOffsets[LineNumber] + BufferInfo -> LocalTextFontBase,Buffer,Length);
  433.     }
  434.  
  435.     if(Length < 0)
  436.         Length = 0;
  437.  
  438.         /* The line doesn't exactly fill the displayed line,
  439.          * so erase the remaining columns.
  440.          */
  441.  
  442.     if(Length < BufferInfo -> BufferLineWidths[LineNumber])
  443.         BufferClear(BufferInfo,BufferInfo -> BufferColumnOffsets[Length],BufferInfo -> BufferLineOffsets[LineNumber],BufferInfo -> BufferColumnOffsets[BufferInfo -> BufferLineWidths[LineNumber]] - 1,BufferInfo -> BufferLineOffsets[LineNumber + 1] - 1);
  444.  
  445.     BufferInfo -> BufferLineWidths[LineNumber] = Length;
  446. }
  447.  
  448.     /* RedrawScreen(LONG FirstLine):
  449.      *
  450.      *    Redraw the contents of the entire screen and return the
  451.      *    number of lines actually drawn.
  452.      */
  453.  
  454. STATIC LONG __regargs
  455. RedrawScreen(TextBufferInfo *BufferInfo,LONG FirstLine)
  456. {
  457.     LONG i,Last,Line = 0,Result;
  458.  
  459.     ObtainSemaphore(BufferSemaphore);
  460.  
  461.         /* Determine last line to display. */
  462.  
  463.     if((Last = FirstLine + BufferInfo -> NumBufferLines) >= Lines)
  464.     {
  465.         Last = Lines;
  466.  
  467.         if((FirstLine = Last - BufferInfo -> NumBufferLines) < 0)
  468.             FirstLine = 0;
  469.  
  470.         BufferInfo -> TopLine = FirstLine;
  471.     }
  472.  
  473.     if(Last > FirstLine + BufferInfo -> NumBufferLines)
  474.         Last = FirstLine + BufferInfo -> NumBufferLines;
  475.  
  476.     Result = Last - FirstLine;
  477.  
  478.     if(Lines)
  479.     {
  480.         if(BufferInfo -> LastTopLine != -1)
  481.         {
  482.             LONG Delta = FirstLine - BufferInfo -> LastTopLine;
  483.  
  484.             if(ABS(Delta) < BufferInfo -> NumBufferLines)
  485.             {
  486.                     /* No change? */
  487.  
  488.                 if(!Delta)
  489.                 {
  490.                     ReleaseSemaphore(BufferSemaphore);
  491.  
  492.                     return(Result);
  493.                 }
  494.                 else
  495.                 {
  496.                     BufferInfo -> LastTopLine = FirstLine;
  497.  
  498.                         /* Scrolled up? */
  499.  
  500.                     if(Delta < 0)
  501.                     {
  502.                         for(i = BufferInfo -> NumBufferLines - 1 ; i >= -Delta ; i--)
  503.                             BufferInfo -> BufferLineWidths[i] = BufferInfo -> BufferLineWidths[i + Delta];
  504.  
  505.                         BufferScroll(BufferInfo,Delta);
  506.  
  507.                         Last = FirstLine - Delta;
  508.                     }
  509.                     else
  510.                     {
  511.                         for(i = Delta ; i < BufferInfo -> NumBufferLines ; i++)
  512.                             BufferInfo -> BufferLineWidths[i - Delta] = BufferInfo -> BufferLineWidths[i];
  513.  
  514.                             /* Scrolled down. */
  515.  
  516.                         BufferScroll(BufferInfo,Delta);
  517.  
  518.                         FirstLine += BufferInfo -> NumBufferLines - Delta;
  519.  
  520.                         Line = BufferInfo -> NumBufferLines - Delta;
  521.                     }
  522.                 }
  523.             }
  524.             else
  525.                 BufferInfo -> LastTopLine = FirstLine;
  526.         }
  527.         else
  528.             BufferInfo -> LastTopLine = FirstLine;
  529.  
  530.         if(BufferLines)
  531.         {
  532.             for(i = FirstLine ; i < Last ; i++)
  533.                 PrintLine(BufferInfo,BufferLines[i],Line++);
  534.         }
  535.     }
  536.  
  537.     ReleaseSemaphore(BufferSemaphore);
  538.  
  539.         /* We didn't fill the whole screen, so clear the rest. */
  540.  
  541.     if(Result < BufferInfo -> NumBufferLines)
  542.     {
  543.         WORD i;
  544.  
  545.         for(i = Result ; i < BufferInfo -> NumBufferLines ; i++)
  546.             BufferInfo -> BufferLineWidths[i] = 0;
  547.  
  548.         BufferClear(BufferInfo,0,BufferInfo -> BufferLineOffsets[Result],BufferInfo -> BufferColumnOffsets[BufferInfo -> NumBufferColumns] - 1,BufferInfo -> BufferLineOffsets[BufferInfo -> NumBufferLines] - 1);
  549.     }
  550.  
  551.     return(Result);
  552. }
  553.  
  554.     /* MarkArea(LONG Column,LONG Line,LONG Length):
  555.      *
  556.      *    Mark an area in the term Buffer window.
  557.      */
  558.  
  559. STATIC VOID __regargs
  560. MarkArea(TextBufferInfo *BufferInfo,LONG Column,LONG Line,LONG Length)
  561. {
  562.     if(BufferInfo -> OldColumn != -1)
  563.         BufferComplement(BufferInfo,BufferInfo -> BufferColumnOffsets[BufferInfo -> OldColumn],BufferInfo -> BufferLineOffsets[BufferInfo -> OldLine],BufferInfo -> BufferColumnOffsets[BufferInfo -> OldLength],BufferInfo -> LocalTextFontHeight);
  564.  
  565.     if(Column != -1)
  566.     {
  567.         if(BufferInfo -> OldColumn != Column || BufferInfo -> OldLine != Line || BufferInfo -> OldLength != Length)
  568.             BufferComplement(BufferInfo,BufferInfo -> BufferColumnOffsets[Column],BufferInfo -> BufferLineOffsets[Line],BufferInfo -> BufferColumnOffsets[Length],BufferInfo -> LocalTextFontHeight);
  569.     }
  570.  
  571.     BufferInfo -> OldColumn    = Column;
  572.     BufferInfo -> OldLine    = Line;
  573.     BufferInfo -> OldLength    = Length;
  574. }
  575.  
  576. STATIC VOID __stdargs
  577. BufferDestructor(struct DataMsg *Item)
  578. {
  579.     Signal(Item -> Client,Item -> Mask);
  580. }
  581.  
  582. STATIC VOID __regargs
  583. BufferSerWrite(TextBufferInfo *BufferInfo,APTR Data,LONG Size)
  584. {
  585.     struct DataMsg Msg;
  586.  
  587.     InitMsgItem(&Msg,BufferDestructor);
  588.  
  589.     Msg . Type        = DATAMSGTYPE_WRITE;
  590.     Msg . Data        = Data;
  591.     Msg . Size        = Size;
  592.     Msg . Client    = FindTask(NULL);
  593.     Msg . Mask        = 1UL << BufferInfo -> BufferSignal;
  594.  
  595.     Forbid();
  596.  
  597.     ClrSignal(Msg . Mask);
  598.  
  599.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  600.  
  601.     Wait(Msg . Mask);
  602.  
  603.     Permit();
  604. }
  605.  
  606.     /* BufferClipPage(struct BlockMarker *Marker):
  607.      *
  608.      *    Send the marked area to the clipboard.
  609.      */
  610.  
  611. STATIC VOID __regargs
  612. BufferClipPage(TextBufferInfo *BufferInfo,struct BlockMarker *Marker)
  613. {
  614.     if(BufferLines)
  615.     {
  616.         struct IFFHandle *Handle;
  617.  
  618.         if(Handle = AllocIFF())
  619.         {
  620.             if(Handle -> iff_Stream = (ULONG)OpenClipboard(Config -> ClipConfig -> ClipboardUnit))
  621.             {
  622.                 InitIFFasClip(Handle);
  623.  
  624.                 if(!OpenIFF(Handle,IFFF_WRITE))
  625.                 {
  626.                     if(!PushChunk(Handle,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN))
  627.                     {
  628.                         if(!PushChunk(Handle,0,ID_CHRS,IFFSIZE_UNKNOWN))
  629.                         {
  630.                             LONG Lines = Marker -> LastLine - Marker -> FirstLine - 1,i;
  631.  
  632.                             if(LINE_WIDTH(BufferLines[Marker -> FirstLine]) > Marker -> FirstColumn)
  633.                                 WriteTrimmedString(Handle,&BufferLines[Marker -> FirstLine][Marker -> FirstColumn],LINE_WIDTH(BufferLines[Marker -> FirstLine]) - Marker -> FirstColumn,BufferInfo -> NeedClipConversion);
  634.  
  635.                             WriteChunkBytes(Handle,"\n",1);
  636.  
  637.                             if(Lines > 0)
  638.                             {
  639.                                 for(i = 0 ; i < Lines ; i++)
  640.                                 {
  641.                                     if(LINE_WIDTH(BufferLines[Marker -> FirstLine + 1 + i]))
  642.                                         WriteTrimmedString(Handle,BufferLines[Marker -> FirstLine + 1 + i],LINE_WIDTH(BufferLines[Marker -> FirstLine + 1 + i]),BufferInfo -> NeedClipConversion);
  643.  
  644.                                     WriteChunkBytes(Handle,"\n",1);
  645.                                 }
  646.                             }
  647.  
  648.                             if(Marker -> LastColumn > LINE_WIDTH(BufferLines[Marker -> LastLine]))
  649.                                 WriteTrimmedString(Handle,BufferLines[Marker -> LastLine],LINE_WIDTH(BufferLines[Marker -> LastLine]),BufferInfo -> NeedClipConversion);
  650.                             else
  651.                                 WriteTrimmedString(Handle,BufferLines[Marker -> LastLine],Marker -> LastColumn,BufferInfo -> NeedClipConversion);
  652.  
  653.                             WriteChunkBytes(Handle,"\n",1);
  654.  
  655.                             PopChunk(Handle);
  656.                         }
  657.  
  658.                         PopChunk(Handle);
  659.                     }
  660.  
  661.                     CloseIFF(Handle);
  662.                 }
  663.  
  664.                 CloseClipboard((struct ClipboardHandle *)Handle -> iff_Stream);
  665.             }
  666.  
  667.             FreeIFF(Handle);
  668.         }
  669.     }
  670. }
  671.  
  672.     /* BufferClip(VOID):
  673.      *
  674.      *    Start buffer marking process.
  675.      */
  676.  
  677. STATIC VOID __regargs
  678. BufferClip(TextBufferInfo *BufferInfo)
  679. {
  680.     struct BlockMarker    *Marker;
  681.     LONG                 FirstX,FirstY;
  682.  
  683.     FirstX = (BufferInfo -> Window -> MouseX - BufferInfo -> Left)    / BufferInfo -> LocalTextFontWidth,
  684.     FirstY = (BufferInfo -> Window -> MouseY - BufferInfo -> Top)    / BufferInfo -> LocalTextFontHeight;
  685.  
  686.     if(Kick30)
  687.         SetMaxPen(BufferInfo -> RPort,(ULONG)~0);
  688.  
  689.     if(Marker = BM_SetMark(BufferInfo -> Window -> RPort,ToggleSelect,ToggleSelect,BufferInfo -> NumBufferColumns,BufferInfo -> NumBufferLines,BufferInfo -> Left,BufferInfo -> Top,BufferInfo -> TopLine,Lines,FirstX,FirstY,BufferInfo -> LocalTextFontWidth,BufferInfo -> LocalTextFontHeight))
  690.     {
  691.         struct IntuiMessage    *Massage;
  692.         ULONG                 Code,IClass;
  693.         BOOLEAN                 Done = FALSE,Aborted = FALSE;
  694.         LONG                 PlusX = BufferInfo -> LocalTextFontWidth - 1,
  695.                              MouseX,MouseY,
  696.                              Delta = 0;
  697.  
  698.         ReportMouse(TRUE,BufferInfo -> Window);
  699.  
  700.         while(!Done)
  701.         {
  702.             WaitPort(BufferInfo -> Window -> UserPort);
  703.  
  704.             while(Massage = (struct IntuiMessage *)GetMsg(BufferInfo -> Window -> UserPort))
  705.             {
  706.                 IClass    = Massage -> Class;
  707.                 Code    = Massage -> Code;
  708.                 MouseX    = Massage -> MouseX - BufferInfo -> Left;
  709.                 MouseY    = Massage -> MouseY - BufferInfo -> Top;
  710.  
  711.                 ReplyMsg(Massage);
  712.  
  713.                 if(IClass == IDCMP_INACTIVEWINDOW)
  714.                 {
  715.                     Done = Aborted = TRUE;
  716.  
  717.                     break;
  718.                 }
  719.  
  720.                 if(IClass == IDCMP_INTUITICKS && Delta != 0)
  721.                 {
  722.                     if(BufferLines)
  723.                     {
  724.                         if((Delta > 0 && BufferInfo -> TopLine + BufferInfo -> NumBufferLines < Lines) || (Delta < 0 && BufferInfo -> TopLine > 0))
  725.                         {
  726.                             if(Delta < 0)
  727.                             {
  728.                                 WORD i;
  729.  
  730.                                 for(i = BufferInfo -> NumBufferLines - 1 ; i > -Delta ; i--)
  731.                                     BufferInfo -> BufferLineWidths[i] = BufferInfo -> BufferLineWidths[i + Delta];
  732.  
  733.                                 if(BufferInfo -> DisplayedLines)
  734.                                     BufferScroll(BufferInfo,Delta);
  735.  
  736.                                 BufferInfo -> BufferLineWidths[0] = BufferInfo -> NumBufferColumns;
  737.  
  738.                                 PrintLine(BufferInfo,BufferLines[--BufferInfo -> TopLine],0);
  739.                             }
  740.                             else
  741.                             {
  742.                                 WORD i;
  743.  
  744.                                 for(i = Delta ; i < BufferInfo -> NumBufferLines ; i++)
  745.                                     BufferInfo -> BufferLineWidths[i - Delta] = BufferInfo -> BufferLineWidths[i];
  746.  
  747.                                 if(BufferInfo -> DisplayedLines)
  748.                                     BufferScroll(BufferInfo,Delta);
  749.  
  750.                                 BufferInfo -> BufferLineWidths[BufferInfo -> NumBufferLines - 1] = BufferInfo -> NumBufferColumns;
  751.  
  752.                                 PrintLine(BufferInfo,BufferLines[BufferInfo -> TopLine + BufferInfo -> NumBufferLines],BufferInfo -> NumBufferLines - 1);
  753.  
  754.                                 BufferInfo -> TopLine++;
  755.                             }
  756.  
  757.                             Marker -> Top     += Delta;
  758.                             Marker -> LastY    -= Delta;
  759.  
  760.                             BM_ExtendMark(Marker,(MouseX + PlusX) / BufferInfo -> LocalTextFontWidth,MouseY / BufferInfo -> LocalTextFontHeight,Delta);
  761.                         }
  762.                         else
  763.                             Delta = 0;
  764.                     }
  765.                 }
  766.  
  767.                 if(IClass == IDCMP_MOUSEBUTTONS && (Code & IECODE_UP_PREFIX))
  768.                 {
  769.                     BM_Draw(Marker,Marker -> Unselect);
  770.  
  771.                     Done = TRUE;
  772.  
  773.                     break;
  774.                 }
  775.  
  776.                 if(IClass == IDCMP_MOUSEMOVE)
  777.                 {
  778.                     BM_ExtendMark(Marker,(MouseX + PlusX) / BufferInfo -> LocalTextFontWidth,MouseY / BufferInfo -> LocalTextFontHeight,0);
  779.  
  780.                     if(MouseY < 1)
  781.                     {
  782.                         if(BufferInfo -> TopLine > 0)
  783.                             Delta = -1;
  784.                     }
  785.                     else
  786.                     {
  787.                         if(MouseY >= BufferInfo -> Height - 1 && BufferInfo -> TopLine + BufferInfo -> NumBufferLines < Lines)
  788.                             Delta = 1;
  789.                     }
  790.  
  791.                     while(Delta)
  792.                     {
  793.                         MouseX    = BufferInfo -> Window -> MouseX - BufferInfo -> Left;
  794.                         MouseY    = BufferInfo -> Window -> MouseY - BufferInfo -> Top;
  795.  
  796.                         if((Delta < 0 && MouseY > 0) || (Delta > 0 && MouseY < BufferInfo -> Height - 1))
  797.                             break;
  798.                         else
  799.                         {
  800.                             if(BufferLines)
  801.                             {
  802.                                 if((Delta > 0 && BufferInfo -> TopLine + BufferInfo -> NumBufferLines < Lines) || (Delta < 0 && BufferInfo -> TopLine > 0))
  803.                                 {
  804.                                     if(Delta < 0)
  805.                                     {
  806.                                         WORD i;
  807.  
  808.                                         for(i = BufferInfo -> NumBufferLines - 1 ; i > -Delta ; i--)
  809.                                             BufferInfo -> BufferLineWidths[i] = BufferInfo -> BufferLineWidths[i + Delta];
  810.  
  811.                                         if(BufferInfo -> DisplayedLines)
  812.                                             BufferScroll(BufferInfo,Delta);
  813.  
  814.                                         BufferInfo -> BufferLineWidths[0] = BufferInfo -> NumBufferColumns;
  815.  
  816.                                         PrintLine(BufferInfo,BufferLines[--BufferInfo -> TopLine],0);
  817.                                     }
  818.                                     else
  819.                                     {
  820.                                         WORD i;
  821.  
  822.                                         for(i = Delta ; i < BufferInfo -> NumBufferLines ; i++)
  823.                                             BufferInfo -> BufferLineWidths[i - Delta] = BufferInfo -> BufferLineWidths[i];
  824.  
  825.                                         if(BufferInfo -> DisplayedLines)
  826.                                             BufferScroll(BufferInfo,Delta);
  827.  
  828.                                         BufferInfo -> BufferLineWidths[BufferInfo -> NumBufferLines - 1] = BufferInfo -> NumBufferColumns;
  829.  
  830.                                         PrintLine(BufferInfo,BufferLines[BufferInfo -> TopLine + BufferInfo -> NumBufferLines],BufferInfo -> NumBufferLines - 1);
  831.  
  832.                                         BufferInfo -> TopLine++;
  833.                                     }
  834.  
  835.                                     Marker -> Top    += Delta;
  836.                                     Marker -> LastY    -= Delta;
  837.  
  838.                                     BM_ExtendMark(Marker,(MouseX + PlusX) / BufferInfo -> LocalTextFontWidth,MouseY / BufferInfo -> LocalTextFontHeight,Delta);
  839.  
  840.                                     SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  841.                                         PGA_Top,BufferInfo -> TopLine,
  842.                                     TAG_DONE);
  843.                                 }
  844.                                 else
  845.                                     break;
  846.                             }
  847.                             else
  848.                                 break;
  849.                         }
  850.                     }
  851.  
  852.                     Delta = 0;
  853.                 }
  854.             }
  855.         }
  856.  
  857.         ReportMouse(FALSE,BufferInfo -> Window);
  858.  
  859.         while(Massage = (struct IntuiMessage *)GetMsg(BufferInfo -> Window -> UserPort))
  860.             ReplyMsg(Massage);
  861.  
  862.         if(!Aborted)
  863.         {
  864.             LONG ThisX,ThisY;
  865.  
  866.             ThisX = (BufferInfo -> Window -> MouseX - BufferInfo -> Left)    / BufferInfo -> LocalTextFontWidth;
  867.             ThisY = (BufferInfo -> Window -> MouseY - BufferInfo -> Top)    / BufferInfo -> LocalTextFontHeight;
  868.  
  869.             if(FirstX != ThisX || FirstY != ThisY)
  870.             {
  871.                 SetWait(BufferInfo -> Window);
  872.  
  873.                 if(Marker -> FirstColumn == Marker -> Width)
  874.                 {
  875.                     Marker -> FirstLine++;
  876.  
  877.                     Marker -> FirstColumn = 0;
  878.                 }
  879.  
  880.                 if(Marker -> LastColumn == 0)
  881.                 {
  882.                     Marker -> LastLine--;
  883.  
  884.                     Marker -> LastColumn = Marker -> Width;
  885.                 }
  886.  
  887.                 if(Marker -> FirstLine <= Marker -> LastLine)
  888.                 {
  889.                     if(Marker -> FirstLine != Marker -> LastLine || Marker -> FirstColumn != Marker -> LastColumn)
  890.                     {
  891.                         if(BufferLines)
  892.                         {
  893.                             if(Marker -> FirstLine == Marker -> LastLine)
  894.                             {
  895.                                 if(BufferInfo -> NeedClipConversion)
  896.                                 {
  897.                                     UBYTE    Buffer[256];
  898.                                     LONG    Len,i;
  899.                                     STRPTR    Dest,
  900.                                             Source    = &BufferLines[Marker -> FirstLine][Marker -> FirstColumn];
  901.                                     LONG    Size    = Marker -> LastColumn - Marker -> FirstColumn;
  902.                                     UBYTE    c;
  903.  
  904.                                     BOOL    FirstWrite = TRUE;
  905.  
  906.                                     do
  907.                                     {
  908.                                         Len = MIN(Size,256);
  909.  
  910.                                         Size -= Len;
  911.  
  912.                                         for(i = 0, Dest = Buffer ; i < Len ; i++)
  913.                                         {
  914.                                             if(c = ISOConversion[*Source++])
  915.                                                 *Dest++ = c;
  916.                                             else
  917.                                                 *Dest++ = ' ';
  918.                                         }
  919.  
  920.                                         if(Dest > Buffer)
  921.                                         {
  922.                                             if(FirstWrite)
  923.                                             {
  924.                                                 FirstWrite = FALSE;
  925.  
  926.                                                 SaveClip(Buffer,(ULONG)Dest - (ULONG)&Buffer[0]);
  927.                                             }
  928.                                             else
  929.                                                 AddClip(Buffer,(ULONG)Dest - (ULONG)&Buffer[0]);
  930.                                         }
  931.                                     }
  932.                                     while(Size > 0);
  933.                                 }
  934.                                 else
  935.                                     SaveClip(&BufferLines[Marker -> FirstLine][Marker -> FirstColumn],Marker -> LastColumn - Marker -> FirstColumn);
  936.                             }
  937.                             else
  938.                                 BufferClipPage(BufferInfo,Marker);
  939.                         }
  940.                     }
  941.                 }
  942.  
  943.                 ClrWait(BufferInfo -> Window);
  944.             }
  945.         }
  946.  
  947.         FreeVecPooled(Marker);
  948.     }
  949.  
  950.     if(Kick30)
  951.         SetMaxPen(BufferInfo -> RPort,BufferInfo -> MaxPen);
  952. }
  953.  
  954. STATIC VOID __regargs
  955. StartSearch(TextBufferInfo *BufferInfo,struct SearchInfo *SearchInfo,STRPTR SearchBuffer)
  956. {
  957.     LT_LockWindow(BufferInfo -> Window);
  958.  
  959.     if(Lines)
  960.     {
  961.         LONG LineNumber;
  962.  
  963.         ObtainSemaphore(BufferSemaphore);
  964.  
  965.         LineNumber = SearchTextBuffer(SearchInfo);
  966.  
  967.         ReleaseSemaphore(BufferSemaphore);
  968.  
  969.         if(LineNumber == -1)
  970.         {
  971.             MyEasyRequest(BufferInfo -> Window,LocaleString(MSG_TERMBUFFER_DID_NOT_FIND_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SearchBuffer);
  972.  
  973.             FlushMsg(BufferInfo -> Window);
  974.  
  975.             SearchInfo -> FoundY = -1;
  976.  
  977.             MarkArea(BufferInfo,-1,-1,-1);
  978.         }
  979.         else
  980.         {
  981.             if(LineNumber < BufferInfo -> TopLine)
  982.             {
  983.                 MarkArea(BufferInfo,-1,-1,-1);
  984.  
  985.                 BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,BufferInfo -> TopLine = LineNumber);
  986.  
  987.                 SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  988.                     PGA_Top,BufferInfo -> TopLine,
  989.                 TAG_DONE);
  990.             }
  991.             else
  992.             {
  993.                 if(LineNumber > BufferInfo -> TopLine + BufferInfo -> DisplayedLines - 1)
  994.                 {
  995.                     MarkArea(BufferInfo,-1,-1,-1);
  996.  
  997.                     if(LineNumber >= Lines - BufferInfo -> NumBufferLines)
  998.                     {
  999.                         LONG NewCurrentLine;
  1000.  
  1001.                         if((NewCurrentLine = Lines - BufferInfo -> NumBufferLines) < 0)
  1002.                             NewCurrentLine = 0;
  1003.  
  1004.                         if(BufferInfo -> TopLine != NewCurrentLine)
  1005.                             BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,BufferInfo -> TopLine = NewCurrentLine);
  1006.                     }
  1007.                     else
  1008.                         BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,BufferInfo -> TopLine = LineNumber);
  1009.  
  1010.                     SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1011.                         PGA_Top,BufferInfo -> TopLine,
  1012.                     TAG_DONE);
  1013.                 }
  1014.             }
  1015.  
  1016.             MarkArea(BufferInfo,SearchInfo -> FoundX,LineNumber - BufferInfo -> TopLine,SearchInfo -> PatternWidth);
  1017.         }
  1018.     }
  1019.     else
  1020.         MyEasyRequest(BufferInfo -> Window,LocaleString(MSG_GLOBAL_NOTHING_IN_THE_BUFFER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
  1021.  
  1022.     LT_UnlockWindow(BufferInfo -> Window);
  1023. }
  1024.  
  1025. STATIC BOOLEAN __regargs
  1026. HandleBuffer(struct SignalSemaphore *Access,TextBufferInfo **Data)
  1027. {
  1028.     ULONG                     LastSeconds    = 0,
  1029.                              LastMicros        = 0,
  1030.                              Seconds,
  1031.                              Micros;
  1032.     BOOLEAN                     ClickAndActivate,
  1033.                              UpdatePercent    = TRUE;
  1034.  
  1035.     ULONG                     SignalSet;
  1036.  
  1037.     struct IntuiMessage        *Massage;
  1038.     ULONG                     MsgClass;
  1039.     UWORD                     MsgCode,MsgQualifier,LastQualifier = NULL;
  1040.     WORD                     MouseX,MouseY;
  1041.  
  1042.     UBYTE                     Char,LastChar = 0,FullChar;
  1043.     LONG                     LastWidth = 0;
  1044.  
  1045.     UBYTE                     PercentBuffer[80];
  1046.     UBYTE                     SearchBuffer[256];
  1047.  
  1048.     struct TagItem            *TagList;
  1049.  
  1050.     STRPTR                     PercentTemplate;
  1051.  
  1052.     BOOLEAN                     RingBack = FALSE;
  1053.  
  1054.     struct SearchContext    *Context    = NULL;
  1055.     struct SearchInfo        *SearchInfo    = NULL;
  1056.  
  1057.     struct Hook                 HistoryHook;
  1058.     TextBufferInfo            *BufferInfo;
  1059.  
  1060.     BufferInfo = *Data;
  1061.  
  1062.     HistoryHook . h_Data = &TextBufferHistory;
  1063.  
  1064.     if(LocaleBase)
  1065.         PercentTemplate = "%lD/%lD (%ld%%)";
  1066.     else
  1067.         PercentTemplate = "%ld/%ld (%ld%%)";
  1068.  
  1069.     FOREVER
  1070.     {
  1071.             /* Show where we are. */
  1072.  
  1073.         if(Lines && UpdatePercent)
  1074.         {
  1075.             SPrintf(PercentBuffer,PercentTemplate,BufferInfo -> TopLine,Lines > BufferInfo -> NumBufferLines ? Lines - BufferInfo -> NumBufferLines : 0,(100 * (BufferInfo -> TopLine + BufferInfo -> DisplayedLines)) / Lines);
  1076.  
  1077.             if(BufferInfo -> Parent)
  1078.             {
  1079.                 SPrintf(BufferInfo -> TitleBuffer,"%s  %s",LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),PercentBuffer);
  1080.  
  1081.                 SetWindowTitles(BufferInfo -> Window,BufferInfo -> TitleBuffer,(STRPTR)~0);
  1082.             }
  1083.             else
  1084.             {
  1085.                 LONG Width,Len;
  1086.  
  1087.                 if(Kick30)
  1088.                     SetABPenDrMd(BufferInfo -> Screen -> BarLayer -> rp,BufferInfo -> TitleFrontPen,BufferInfo -> TitleBackPen,JAM2);
  1089.                 else
  1090.                 {
  1091.                     SetAPen(BufferInfo -> Screen -> BarLayer -> rp,BufferInfo -> TitleFrontPen);
  1092.                     SetBPen(BufferInfo -> Screen -> BarLayer -> rp,BufferInfo -> TitleBackPen);
  1093.                     SetDrMd(BufferInfo -> Screen -> BarLayer -> rp,JAM2);
  1094.                 }
  1095.  
  1096.                 Len = strlen(PercentBuffer);
  1097.  
  1098.                 Move(BufferInfo -> Screen -> BarLayer -> rp,BufferInfo -> TitleOffset,BufferInfo -> Screen -> BarLayer -> rp -> Font -> tf_Baseline + 1);
  1099.                 Text(BufferInfo -> Screen -> BarLayer -> rp,PercentBuffer,Len);
  1100.  
  1101.                 Width = TextLength(BufferInfo -> Screen -> BarLayer -> rp,PercentBuffer,Len);
  1102.  
  1103.                 if(LastWidth > Width)
  1104.                 {
  1105.                     SetAPen(BufferInfo -> Screen -> BarLayer -> rp,BufferInfo -> TitleBackPen);
  1106.                     RectFill(BufferInfo -> Screen -> BarLayer -> rp,BufferInfo -> TitleOffset + Width,1,BufferInfo -> TitleOffset + LastWidth - 1,BufferInfo -> Screen -> BarLayer -> rp -> Font -> tf_YSize);
  1107.                 }
  1108.  
  1109.                 LastWidth = Width;
  1110.             }
  1111.  
  1112.             UpdatePercent = FALSE;
  1113.         }
  1114.  
  1115.         if(BufferInfo -> BufferTerminated)
  1116.         {
  1117.             ObtainSemaphore(Access);
  1118.  
  1119.             SignalSet = SetSignal(0,SIG_KILL | SIG_TOFRONT | SIG_UPDATE | SIG_MOVEUP | PORTMASK(BufferInfo -> Window -> UserPort) | BufferInfo -> QueueMask) & (SIG_KILL | SIG_TOFRONT | SIG_UPDATE | SIG_MOVEUP | PORTMASK(BufferInfo -> Window -> UserPort) | BufferInfo -> QueueMask);
  1120.  
  1121.                 // Disconnect
  1122.  
  1123.             if(!SignalSet)
  1124.             {
  1125.                 BufferInfo -> Buddy = NULL;
  1126.  
  1127.                 *Data = NULL;
  1128.  
  1129.                 ReleaseSemaphore(Access);
  1130.  
  1131.                 break;
  1132.             }
  1133.             else
  1134.                 ReleaseSemaphore(Access);
  1135.         }
  1136.         else
  1137.             SignalSet = Wait(SIG_KILL | SIG_TOFRONT | SIG_UPDATE | SIG_MOVEUP | PORTMASK(BufferInfo -> Window -> UserPort) | BufferInfo -> QueueMask);
  1138.  
  1139.             /* Leave the town? */
  1140.  
  1141.         if(SignalSet & SIG_KILL)
  1142.             BufferInfo -> BufferTerminated = RingBack = TRUE;
  1143.  
  1144.             /* Bring our window to the front. */
  1145.  
  1146.         if(SignalSet & SIG_TOFRONT)
  1147.         {
  1148.             if(Context)
  1149.                 LT_ShowWindow(Context -> SearchHandle,TRUE);
  1150.  
  1151.             BumpWindow(BufferInfo -> Window);
  1152.         }
  1153.  
  1154.             /* We've got one more line in the
  1155.              * buffer.
  1156.              */
  1157.  
  1158.         if(SignalSet & SIG_UPDATE)
  1159.         {
  1160.             MarkArea(BufferInfo,-1,-1,-1);
  1161.  
  1162.             if(BufferLines && Lines)
  1163.             {
  1164.                 if(Lines - BufferInfo -> TopLine > BufferInfo -> DisplayedLines && BufferInfo -> DisplayedLines < BufferInfo -> NumBufferLines)
  1165.                 {
  1166.                     LONG i = BufferInfo -> TopLine + BufferInfo -> DisplayedLines;
  1167.  
  1168.                     do
  1169.                         PrintLine(BufferInfo,BufferLines[i++],BufferInfo -> DisplayedLines++);
  1170.                     while(BufferInfo -> DisplayedLines < BufferInfo -> NumBufferLines && i < Lines);
  1171.                 }
  1172.             }
  1173.             else
  1174.                 BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,BufferInfo -> TopLine = 0);
  1175.  
  1176.             SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1177.                 PGA_Total,        Lines,
  1178.                 PGA_Visible,    BufferInfo -> DisplayedLines,
  1179.             TAG_DONE);
  1180.  
  1181.             UpdatePercent = TRUE;
  1182.  
  1183.             Signal(ThisProcess,SIG_HANDSHAKE);
  1184.         }
  1185.  
  1186.             /* The contents of the buffer have moved
  1187.              * up a line.
  1188.              */
  1189.  
  1190.         if(SignalSet & SIG_MOVEUP)
  1191.         {
  1192.             MarkArea(BufferInfo,-1,-1,-1);
  1193.  
  1194.             if(BufferInfo -> TopLine > 0)
  1195.             {
  1196.                 BufferInfo -> LastTopLine = --BufferInfo -> TopLine;
  1197.  
  1198.                 SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1199.                     PGA_Top,BufferInfo -> TopLine,
  1200.                 TAG_DONE);
  1201.             }
  1202.             else
  1203.             {
  1204.                 LONG i;
  1205.  
  1206.                 for(i = 0 ; i < BufferInfo -> NumBufferLines - 1 ; i++)
  1207.                     BufferInfo -> BufferLineWidths[i] = BufferInfo -> BufferLineWidths[i + 1];
  1208.  
  1209.                 BufferScroll(BufferInfo,-1);
  1210.  
  1211.                 PrintLine(BufferInfo,BufferLines[BufferInfo -> NumBufferLines - 1],BufferInfo -> NumBufferLines - 1);
  1212.             }
  1213.  
  1214.             UpdatePercent = TRUE;
  1215.  
  1216.             Signal(ThisProcess,SIG_HANDSHAKE);
  1217.         }
  1218.  
  1219.             // A request from the queue?
  1220.  
  1221.         if(SignalSet & BufferInfo -> QueueMask)
  1222.         {
  1223.             struct DataMsg    *Msg;
  1224.             LONG             NewCurrentLine;
  1225.  
  1226.             while(Msg = (struct DataMsg *)GetMsgItem(BufferInfo -> Queue))
  1227.             {
  1228.                 switch(Msg -> Size)
  1229.                 {
  1230.                     case REVIEW_MOVE_TOP:
  1231.  
  1232.                         MarkArea(BufferInfo,-1,-1,-1);
  1233.  
  1234.                         if(BufferInfo -> TopLine)
  1235.                         {
  1236.                             BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,0);
  1237.  
  1238.                             BufferInfo -> TopLine = 0;
  1239.                             LastChar = 0;
  1240.  
  1241.                             SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1242.                                 PGA_Top,BufferInfo -> TopLine,
  1243.                             TAG_DONE);
  1244.  
  1245.                             UpdatePercent = TRUE;
  1246.                         }
  1247.  
  1248.                         break;
  1249.  
  1250.                     case REVIEW_MOVE_BOTTOM:
  1251.  
  1252.                         if((NewCurrentLine = Lines - BufferInfo -> NumBufferLines) < 0)
  1253.                             NewCurrentLine = 0;
  1254.  
  1255.                         MarkArea(BufferInfo,-1,-1,-1);
  1256.  
  1257.                         if(BufferInfo -> TopLine != NewCurrentLine)
  1258.                         {
  1259.                             BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,NewCurrentLine);
  1260.  
  1261.                             BufferInfo -> TopLine = NewCurrentLine;
  1262.  
  1263.                             LastChar = 0;
  1264.  
  1265.                             SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1266.                                 PGA_Top,BufferInfo -> TopLine,
  1267.                             TAG_DONE);
  1268.  
  1269.                             UpdatePercent = TRUE;
  1270.                         }
  1271.  
  1272.                         break;
  1273.  
  1274.                     case REVIEW_MOVE_UP:
  1275.  
  1276.                         if((NewCurrentLine = BufferInfo -> TopLine - BufferInfo -> NumBufferLines) < 0)
  1277.                             NewCurrentLine = 0;
  1278.  
  1279.                         MarkArea(BufferInfo,-1,-1,-1);
  1280.  
  1281.                         if(NewCurrentLine != BufferInfo -> TopLine)
  1282.                         {
  1283.                             BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,NewCurrentLine);
  1284.  
  1285.                             BufferInfo -> TopLine = NewCurrentLine;
  1286.  
  1287.                             LastChar = 0;
  1288.  
  1289.                             SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1290.                                 PGA_Top,BufferInfo -> TopLine,
  1291.                             TAG_DONE);
  1292.  
  1293.                             UpdatePercent = TRUE;
  1294.                         }
  1295.  
  1296.                         break;
  1297.  
  1298.                     case REVIEW_MOVE_DOWN:
  1299.  
  1300.                         if((NewCurrentLine = BufferInfo -> TopLine + (2 * BufferInfo -> NumBufferLines)) > Lines)
  1301.                             NewCurrentLine = Lines;
  1302.  
  1303.                         if((NewCurrentLine = NewCurrentLine - BufferInfo -> NumBufferLines) < 0)
  1304.                             NewCurrentLine = 0;
  1305.  
  1306.                         MarkArea(BufferInfo,-1,-1,-1);
  1307.  
  1308.                         if(NewCurrentLine != BufferInfo -> TopLine)
  1309.                         {
  1310.                             BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,NewCurrentLine);
  1311.  
  1312.                             BufferInfo -> TopLine = NewCurrentLine;
  1313.  
  1314.                             LastChar = 0;
  1315.  
  1316.                             SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1317.                                 PGA_Top,BufferInfo -> TopLine,
  1318.                             TAG_DONE);
  1319.  
  1320.                             UpdatePercent = TRUE;
  1321.                         }
  1322.  
  1323.                         break;
  1324.                 }
  1325.  
  1326.                 DeleteMsgItem(Msg);
  1327.             }
  1328.         }
  1329.  
  1330.             /* Process the incoming window
  1331.              * input.
  1332.              */
  1333.  
  1334.         while(Massage = (struct IntuiMessage *)GetMsg(BufferInfo -> Window -> UserPort))
  1335.         {
  1336.             if(Context && Context -> SearchWindow == Massage -> IDCMPWindow)
  1337.             {
  1338.                 MsgClass = NULL;
  1339.  
  1340.                 if(HandleSearchMessage(Context,&Massage))
  1341.                 {
  1342.                     BOOLEAN Ok = Context -> Ok;
  1343.  
  1344.                     DeleteSearchContext(Context);
  1345.  
  1346.                     Context = NULL;
  1347.  
  1348.                     if(Ok)
  1349.                     {
  1350.                         if(SearchInfo)
  1351.                             DeleteSearchInfo(SearchInfo);
  1352.  
  1353.                         if(SearchInfo = CreateSearchInfo(SearchBuffer,BufferInfo -> SearchForward,BufferInfo -> IgnoreCase,BufferInfo -> WholeWords))
  1354.                             StartSearch(BufferInfo,SearchInfo,SearchBuffer);
  1355.                     }
  1356.                     else
  1357.                     {
  1358.                         if(SearchInfo)
  1359.                             DeleteSearchInfo(SearchInfo);
  1360.  
  1361.                         SearchInfo = NULL;
  1362.                     }
  1363.                 }
  1364.             }
  1365.             else
  1366.             {
  1367.                 MsgClass        = Massage -> Class;
  1368.                 MsgCode            = Massage -> Code;
  1369.                 MsgQualifier    = Massage -> Qualifier;
  1370.                 MouseX            = Massage -> MouseX - BufferInfo -> Left;
  1371.                 MouseY            = Massage -> MouseY - BufferInfo -> Top;
  1372.                 TagList            = (struct TagItem *)Massage -> IAddress;
  1373.                 Seconds            = Massage -> Seconds;
  1374.                 Micros            = Massage -> Micros;
  1375.  
  1376.                 ClickAndActivate = FALSE;
  1377.  
  1378.                 if(Seconds == LastSeconds && Micros == LastMicros)
  1379.                 {
  1380.                     if(Massage -> Class == IDCMP_ACTIVEWINDOW || Massage -> Class == IDCMP_MOUSEBUTTONS)
  1381.                         ClickAndActivate = TRUE;
  1382.                 }
  1383.  
  1384.                 LastSeconds    = Seconds;
  1385.                 LastMicros    = Micros;
  1386.  
  1387.                     /* This hack is necessary to obtain the
  1388.                      * character codes generated for the cursor
  1389.                      * keys. A control or alternate qualifier
  1390.                      * would spoil the result (i.e. we would
  1391.                      * not get a valid key code).
  1392.                      */
  1393.  
  1394.                 Massage -> Qualifier = NULL;
  1395.  
  1396.                 Char = KeyConvert(Massage,NULL,NULL);
  1397.  
  1398.                     // Put the qualifier back and do it all again
  1399.  
  1400.                 Massage -> Qualifier = MsgQualifier;
  1401.  
  1402.                 FullChar = KeyConvert(Massage,NULL,NULL);
  1403.  
  1404.                 ReplyMsg((struct Message *)Massage);
  1405.             }
  1406.  
  1407.             if(MsgClass == IDCMP_ACTIVEWINDOW)
  1408.                 UpdatePercent = TRUE;
  1409.  
  1410.             if(MsgClass == IDCMP_IDCMPUPDATE)
  1411.             {
  1412.                 switch(GetTagData(GA_ID,0,TagList))
  1413.                 {
  1414.                     case GAD_UP:
  1415.  
  1416.                         if(BufferInfo -> TopLine > 0)
  1417.                         {
  1418.                             BufferInfo -> TopLine--;
  1419.  
  1420.                             MarkArea(BufferInfo,-1,-1,-1);
  1421.  
  1422.                             SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1423.                                 PGA_Top,BufferInfo -> TopLine,
  1424.                             TAG_DONE);
  1425.  
  1426.                             BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,BufferInfo -> TopLine);
  1427.  
  1428.                             UpdatePercent = TRUE;
  1429.                         }
  1430.  
  1431.                         break;
  1432.  
  1433.                     case GAD_DOWN:
  1434.  
  1435.                         if(BufferInfo -> TopLine + BufferInfo -> NumBufferLines < Lines)
  1436.                         {
  1437.                             BufferInfo -> TopLine++;
  1438.  
  1439.                             MarkArea(BufferInfo,-1,-1,-1);
  1440.  
  1441.                             SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1442.                                 PGA_Top,BufferInfo -> TopLine,
  1443.                             TAG_DONE);
  1444.  
  1445.                             BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,BufferInfo -> TopLine);
  1446.  
  1447.                             UpdatePercent = TRUE;
  1448.                         }
  1449.  
  1450.                         break;
  1451.                 }
  1452.             }
  1453.  
  1454.             if(MsgClass == IDCMP_MOUSEMOVE || MsgClass == IDCMP_GADGETDOWN || MsgClass == IDCMP_GADGETUP)
  1455.             {
  1456.                 LONG Position;
  1457.  
  1458.                 GetAttr(PGA_Top,BufferInfo -> Scroller,(ULONG *)&Position);
  1459.  
  1460.                 if(Position != BufferInfo -> TopLine)
  1461.                 {
  1462.                     MarkArea(BufferInfo,-1,-1,-1);
  1463.  
  1464.                     BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,BufferInfo -> TopLine = Position);
  1465.  
  1466.                     UpdatePercent = TRUE;
  1467.                 }
  1468.             }
  1469.  
  1470.             if(MsgClass == IDCMP_RAWKEY)
  1471.             {
  1472.                 if(MsgCode == HELP_CODE)
  1473.                     GuideDisplay(CONTEXT_TEXTBUFFER);
  1474.  
  1475.                 if(LastChar)
  1476.                 {
  1477.                     if((MsgCode & IECODE_UP_PREFIX) || !(LastQualifier & IEQUALIFIER_REPEAT))
  1478.                     {
  1479.                         SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1480.                             PGA_Top,BufferInfo -> TopLine,
  1481.                         TAG_DONE);
  1482.  
  1483.                         UpdatePercent = TRUE;
  1484.                     }
  1485.                 }
  1486.  
  1487.                 if(LastChar = Char)
  1488.                 {
  1489.                         /* Use the numeric keypad keys to
  1490.                          * move through the buffer.
  1491.                          */
  1492.  
  1493.                     if(MsgQualifier & IEQUALIFIER_NUMERICPAD)
  1494.                     {
  1495.                             /* Remove the numpad qualifier. */
  1496.  
  1497.                         MsgQualifier &= ~IEQUALIFIER_NUMERICPAD;
  1498.  
  1499.                         switch(Char - '0')
  1500.                         {
  1501.                                 /* Jump to bottom. */
  1502.  
  1503.                             case 1:
  1504.  
  1505.                                 Char = CDN;
  1506.                                 MsgQualifier |= IEQUALIFIER_CONTROL;
  1507.                                 break;
  1508.  
  1509.                                 /* Jump to top. */
  1510.  
  1511.                             case 7:
  1512.  
  1513.                                 Char = CUP;
  1514.                                 MsgQualifier |= IEQUALIFIER_CONTROL;
  1515.                                 break;
  1516.  
  1517.                                 /* Move one page down. */
  1518.  
  1519.                             case 3:
  1520.  
  1521.                                 Char = CDN;
  1522.                                 MsgQualifier |= IEQUALIFIER_LSHIFT;
  1523.                                 break;
  1524.  
  1525.                                 /* Move one page up. */
  1526.  
  1527.                             case 9:
  1528.  
  1529.                                 Char = CUP;
  1530.                                 MsgQualifier |= IEQUALIFIER_LSHIFT;
  1531.                                 break;
  1532.  
  1533.                                 /* Move one line down. */
  1534.  
  1535.                             case 2:
  1536.  
  1537.                                 Char = CDN;
  1538.                                 break;
  1539.  
  1540.                                 /* Move one line up. */
  1541.  
  1542.                             case 8:
  1543.  
  1544.                                 Char = CUP;
  1545.                                 break;
  1546.                         }
  1547.                     }
  1548.  
  1549.                         /* Check cursor keys. */
  1550.  
  1551.                     switch(Char)
  1552.                     {
  1553.                             /* Scroll the buffer up. */
  1554.  
  1555.                         case CUP:
  1556.  
  1557.                             if(MsgQualifier & (IEQUALIFIER_CONTROL | IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  1558.                             {
  1559.                                 MarkArea(BufferInfo,-1,-1,-1);
  1560.  
  1561.                                 if(BufferInfo -> TopLine)
  1562.                                 {
  1563.                                     BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,0);
  1564.  
  1565.                                     BufferInfo -> TopLine = 0;
  1566.                                     LastChar = 0;
  1567.  
  1568.                                     SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1569.                                         PGA_Top,BufferInfo -> TopLine,
  1570.                                     TAG_DONE);
  1571.  
  1572.                                     UpdatePercent = TRUE;
  1573.                                 }
  1574.  
  1575.                                 break;
  1576.                             }
  1577.  
  1578.                             if(MsgQualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1579.                             {
  1580.                                 LONG NewCurrentLine;
  1581.  
  1582.                                 if((NewCurrentLine = BufferInfo -> TopLine - BufferInfo -> NumBufferLines) < 0)
  1583.                                     NewCurrentLine = 0;
  1584.  
  1585.                                 MarkArea(BufferInfo,-1,-1,-1);
  1586.  
  1587.                                 if(NewCurrentLine != BufferInfo -> TopLine)
  1588.                                 {
  1589.                                     BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,NewCurrentLine);
  1590.  
  1591.                                     BufferInfo -> TopLine = NewCurrentLine;
  1592.  
  1593.                                     LastChar = 0;
  1594.  
  1595.                                     SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1596.                                         PGA_Top,BufferInfo -> TopLine,
  1597.                                     TAG_DONE);
  1598.  
  1599.                                     UpdatePercent = TRUE;
  1600.                                 }
  1601.  
  1602.                                 break;
  1603.                             }
  1604.  
  1605.                             if(BufferInfo -> TopLine)
  1606.                             {
  1607.                                 MarkArea(BufferInfo,-1,-1,-1);
  1608.  
  1609.                                 BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,--BufferInfo -> TopLine);
  1610.  
  1611.                                 UpdatePercent = TRUE;
  1612.                             }
  1613.  
  1614.                             break;
  1615.  
  1616.                             /* Scroll the buffer down. */
  1617.  
  1618.                         case CDN:
  1619.  
  1620.                             if(MsgQualifier & (IEQUALIFIER_CONTROL | IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  1621.                             {
  1622.                                 LONG NewCurrentLine;
  1623.  
  1624.                                 if((NewCurrentLine = Lines - BufferInfo -> NumBufferLines) < 0)
  1625.                                     NewCurrentLine = 0;
  1626.  
  1627.                                 MarkArea(BufferInfo,-1,-1,-1);
  1628.  
  1629.                                 if(BufferInfo -> TopLine != NewCurrentLine)
  1630.                                 {
  1631.                                     BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,NewCurrentLine);
  1632.  
  1633.                                     BufferInfo -> TopLine = NewCurrentLine;
  1634.  
  1635.                                     LastChar = 0;
  1636.  
  1637.                                     SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1638.                                         PGA_Top,BufferInfo -> TopLine,
  1639.                                     TAG_DONE);
  1640.  
  1641.                                     UpdatePercent = TRUE;
  1642.                                 }
  1643.  
  1644.                                 break;
  1645.                             }
  1646.  
  1647.                             if(MsgQualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1648.                             {
  1649.                                 LONG NewCurrentLine;
  1650.  
  1651.                                 if((NewCurrentLine = BufferInfo -> TopLine + (2 * BufferInfo -> NumBufferLines)) > Lines)
  1652.                                     NewCurrentLine = Lines;
  1653.  
  1654.                                 if((NewCurrentLine = NewCurrentLine - BufferInfo -> NumBufferLines) < 0)
  1655.                                     NewCurrentLine = 0;
  1656.  
  1657.                                 MarkArea(BufferInfo,-1,-1,-1);
  1658.  
  1659.                                 if(NewCurrentLine != BufferInfo -> TopLine)
  1660.                                 {
  1661.                                     BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,NewCurrentLine);
  1662.  
  1663.                                     BufferInfo -> TopLine = NewCurrentLine;
  1664.  
  1665.                                     LastChar = 0;
  1666.  
  1667.                                     SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1668.                                         PGA_Top,BufferInfo -> TopLine,
  1669.                                     TAG_DONE);
  1670.  
  1671.                                     UpdatePercent = TRUE;
  1672.                                 }
  1673.  
  1674.                                 break;
  1675.                             }
  1676.  
  1677.                             if(BufferInfo -> TopLine + BufferInfo -> NumBufferLines < Lines)
  1678.                             {
  1679.                                 MarkArea(BufferInfo,-1,-1,-1);
  1680.  
  1681.                                 BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,BufferInfo -> TopLine + 1);
  1682.  
  1683.                                 BufferInfo -> TopLine++;
  1684.  
  1685.                                 UpdatePercent = TRUE;
  1686.                             }
  1687.  
  1688.                             break;
  1689.  
  1690.                         default:
  1691.  
  1692.                             if(BufferInfo -> Parent)
  1693.                             {
  1694.                                 Char = FullChar;
  1695.  
  1696.                                 if(Config -> SerialConfig -> StripBit8)
  1697.                                     Char &= 0x7F;
  1698.  
  1699.                                 if(Status == STATUS_HOLDING)
  1700.                                 {
  1701.                                     if(Char == XOF)
  1702.                                     {
  1703.                                         BufferSerWrite(BufferInfo,&Char,1);
  1704.  
  1705.                                         Status = STATUS_READY;
  1706.                                     }
  1707.                                 }
  1708.                                 else
  1709.                                 {
  1710.                                         // Convert chars as appropriate
  1711.  
  1712.                                     if(Char == '\n')
  1713.                                     {
  1714.                                         switch(Config -> TerminalConfig -> SendLF)
  1715.                                         {
  1716.                                             case EOL_LF:
  1717.  
  1718.                                                 goto SendIt;
  1719.  
  1720.                                             case EOL_LFCR:
  1721.  
  1722.                                                 BufferSerWrite(BufferInfo,"\n\r",2);
  1723.                                                 break;
  1724.  
  1725.                                             case EOL_CRLF:
  1726.  
  1727.                                                 BufferSerWrite(BufferInfo,"\r\n",2);
  1728.                                                 break;
  1729.  
  1730.                                             case EOL_CR:
  1731.  
  1732.                                                 BufferSerWrite(BufferInfo,"\r",1);
  1733.                                                 break;
  1734.                                         }
  1735.                                     }
  1736.  
  1737.                                     if(Char == '\r')
  1738.                                     {
  1739.                                         switch(Config -> TerminalConfig -> SendCR)
  1740.                                         {
  1741.                                             case EOL_CR:
  1742.  
  1743.                                                 goto SendIt;
  1744.  
  1745.                                             case EOL_LFCR:
  1746.  
  1747.                                                 BufferSerWrite(BufferInfo,"\n\r",2);
  1748.                                                 break;
  1749.  
  1750.                                             case EOL_CRLF:
  1751.  
  1752.                                                 BufferSerWrite(BufferInfo,"\r\n",2);
  1753.                                                 break;
  1754.  
  1755.                                             case EOL_LF:
  1756.  
  1757.                                                 BufferSerWrite(BufferInfo,"\n",1);
  1758.                                                 break;
  1759.                                         }
  1760.                                     }
  1761.  
  1762.                                         /* Stop in/output. */
  1763.  
  1764.                                     if(Char == XON)
  1765.                                     {
  1766.                                         if(Config -> SerialConfig -> PassThrough)
  1767.                                             BufferSerWrite(BufferInfo,&Char,1);
  1768.  
  1769.                                         if(Config -> SerialConfig -> xONxOFF)
  1770.                                             Status = STATUS_HOLDING;
  1771.                                     }
  1772.  
  1773.                                         /* Restart in/output. */
  1774.  
  1775.                                     if(Char == XOF)
  1776.                                     {
  1777.                                         if(Config -> SerialConfig -> PassThrough)
  1778.                                             BufferSerWrite(BufferInfo,&Char,1);
  1779.  
  1780.                                         if(Status == STATUS_HOLDING)
  1781.                                             Status = STATUS_READY;
  1782.                                     }
  1783.  
  1784.                                         /* Convert special
  1785.                                          * Amiga characters into
  1786.                                          * alien IBM dialect.
  1787.                                          */
  1788.  
  1789. SendIt:                                if(Config -> TerminalConfig -> FontMode == FONT_IBM)
  1790.                                     {
  1791.                                         if(IBMConversion[Char])
  1792.                                             BufferSerWrite(BufferInfo,&IBMConversion[Char],1);
  1793.                                         else
  1794.                                             BufferSerWrite(BufferInfo,&Char,1);
  1795.                                     }
  1796.                                     else
  1797.                                         BufferSerWrite(BufferInfo,&Char,1);
  1798.                             }
  1799.  
  1800.                             break;
  1801.                         }
  1802.                     }
  1803.  
  1804.                     LastQualifier = MsgQualifier;
  1805.                 }
  1806.                 else
  1807.                     LastQualifier = NULL;
  1808.  
  1809.                 continue;
  1810.             }
  1811.  
  1812.                 /* User hit a mouse button. */
  1813.  
  1814.             if(MsgClass == IDCMP_MOUSEBUTTONS && (!ClickAndActivate || MsgCode != SELECTDOWN) && !(MsgCode & IECODE_UP_PREFIX))
  1815.             {
  1816.                 MarkArea(BufferInfo,-1,-1,-1);
  1817.  
  1818.                     /* Reasonable dimensions? */
  1819.  
  1820.                 if(MouseY / BufferInfo -> LocalTextFontHeight < BufferInfo -> DisplayedLines && MouseX / BufferInfo -> LocalTextFontWidth < BufferInfo -> NumBufferColumns)
  1821.                 {
  1822.                     ObtainSemaphore(BufferSemaphore);
  1823.  
  1824.                     BufferClip(BufferInfo);
  1825.  
  1826.                     UpdatePercent = TRUE;
  1827.  
  1828.                     BufferInfo -> LastTopLine = BufferInfo -> TopLine;
  1829.  
  1830.                     ReleaseSemaphore(BufferSemaphore);
  1831.  
  1832.                     if(MsgQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  1833.                     {
  1834.                         struct DataMsg Msg;
  1835.  
  1836.                         InitMsgItem(&Msg,BufferDestructor);
  1837.  
  1838.                         Msg . Type        = DATAMSGTYPE_WRITECLIP;
  1839.                         Msg . Size        = Config -> ClipConfig -> ClipboardUnit;
  1840.                         Msg . Client    = FindTask(NULL);
  1841.                         Msg . Mask        = 1UL << BufferInfo -> BufferSignal;
  1842.  
  1843.                         Forbid();
  1844.  
  1845.                         ClrSignal(1L << BufferInfo -> BufferSignal);
  1846.  
  1847.                         PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  1848.  
  1849.                         Wait(1L << BufferInfo -> BufferSignal);
  1850.  
  1851.                         Permit();
  1852.                     }
  1853.  
  1854.                     break;
  1855.                 }
  1856.             }
  1857.  
  1858.             if(MsgClass == IDCMP_MENUHELP)
  1859.                 GuideDisplay(CONTEXT_BUFFER_MENU);
  1860.  
  1861.             if(MsgClass == IDCMP_CLOSEWINDOW)
  1862.                 BufferInfo -> BufferTerminated = TRUE;
  1863.  
  1864.             if(MsgClass == IDCMP_NEWSIZE)
  1865.             {
  1866.                 UWORD Width,Height;
  1867.  
  1868.                 MarkArea(BufferInfo,-1,-1,-1);
  1869.  
  1870.                 BufferInfo -> LastTopLine = -1;
  1871.  
  1872.                 BufferInfo -> Width                = BufferInfo -> Window -> Width        - (BufferInfo -> Window -> BorderLeft    + BufferInfo -> Window -> BorderRight);
  1873.                 BufferInfo -> Height            = BufferInfo -> Window -> Height    - (BufferInfo -> Window -> BorderTop    + BufferInfo -> Window -> BorderBottom);
  1874.  
  1875.                 Width                            = BufferInfo -> Width    - (BufferInfo -> Width    % BufferInfo -> LocalTextFontWidth);
  1876.                 Height                            = BufferInfo -> Height    - (BufferInfo -> Height    % BufferInfo -> LocalTextFontHeight);
  1877.  
  1878.                 BufferInfo -> NumBufferColumns    = BufferInfo -> Width / BufferInfo -> LocalTextFontWidth;
  1879.                 BufferInfo -> NumBufferLines    = BufferInfo -> Height / BufferInfo -> LocalTextFontHeight;
  1880.  
  1881.                 if(Width < BufferInfo -> Width)
  1882.                     BufferClear(BufferInfo,Width,0,BufferInfo -> Width - 1,BufferInfo -> Height - 1);
  1883.  
  1884.                 if(Height < BufferInfo -> Height)
  1885.                     BufferClear(BufferInfo,0,Height,BufferInfo -> Width - 1,BufferInfo -> Height - 1);
  1886.  
  1887.                 BufferInfo -> Width                = Width;
  1888.                 BufferInfo -> Height            = Height;
  1889.  
  1890.                 BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,BufferInfo -> TopLine);
  1891.  
  1892.                 SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  1893.                     PGA_Total,        Lines,
  1894.                     PGA_Top,        BufferInfo -> TopLine,
  1895.                     PGA_Visible,    BufferInfo -> DisplayedLines,
  1896.                 TAG_DONE);
  1897.  
  1898.                 UpdatePercent = TRUE;
  1899.             }
  1900.  
  1901.             if(MsgClass == IDCMP_MENUPICK)
  1902.             {
  1903.                 struct MenuItem    *MenuItem;
  1904.                 struct DataMsg     Msg;
  1905.  
  1906.                 while(MsgCode != MENUNULL)
  1907.                 {
  1908.                     if(MenuItem = ItemAddress(BufferInfo -> BufferMenuStrip,MsgCode))
  1909.                     {
  1910.                         switch((ULONG)GTMENUITEM_USERDATA(MenuItem))
  1911.                         {
  1912.                             case MEN_PASTECLIP:
  1913.  
  1914.                                 InitMsgItem(&Msg,BufferDestructor);
  1915.  
  1916.                                 Msg . Type        = DATAMSGTYPE_WRITECLIP;
  1917.                                 Msg . Size        = Config -> ClipConfig -> ClipboardUnit;
  1918.                                 Msg . Client    = FindTask(NULL);
  1919.                                 Msg . Mask        = 1UL << BufferInfo -> BufferSignal;
  1920.  
  1921.                                 Forbid();
  1922.  
  1923.                                 ClrSignal(Msg . Mask);
  1924.  
  1925.                                 PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  1926.  
  1927.                                 Wait(Msg . Mask);
  1928.  
  1929.                                 Permit();
  1930.                                 break;
  1931.  
  1932.                             case MEN_SEARCH:
  1933.  
  1934.                                 if(Context)
  1935.                                     LT_ShowWindow(Context -> SearchHandle,TRUE);
  1936.                                 else
  1937.                                     Context = CreateSearchContext(BufferInfo -> Window,SearchBuffer,&HistoryHook,&BufferInfo -> SearchForward,&BufferInfo -> IgnoreCase,&BufferInfo -> WholeWords);
  1938.  
  1939.                                 UpdatePercent = TRUE;
  1940.  
  1941.                                 break;
  1942.  
  1943.                             case MEN_REPEAT:
  1944.  
  1945.                                 if(Context)
  1946.                                     LT_ShowWindow(Context -> SearchHandle,TRUE);
  1947.                                 else
  1948.                                 {
  1949.                                     if(SearchInfo)
  1950.                                         StartSearch(BufferInfo,SearchInfo,SearchBuffer);
  1951.                                     else
  1952.                                         Context = CreateSearchContext(BufferInfo -> Window,SearchBuffer,&HistoryHook,&BufferInfo -> SearchForward,&BufferInfo -> IgnoreCase,&BufferInfo -> WholeWords);
  1953.                                 }
  1954.  
  1955.                                 UpdatePercent = TRUE;
  1956.  
  1957.                                 break;
  1958.  
  1959.                             case MEN_GOTO:
  1960.  
  1961.                                 if(Window)
  1962.                                     BumpWindow(Window);
  1963.  
  1964.                                 break;
  1965.  
  1966.                             case MEN_QUITBUF:
  1967.  
  1968.                                 BufferInfo -> BufferTerminated = TRUE;
  1969.                                 break;
  1970.  
  1971.                             case MEN_CLEARBUF_CONTENTS:
  1972.  
  1973.                                 if(Lines)
  1974.                                 {
  1975.                                     struct DataMsg *Msg;
  1976.  
  1977.                                     if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg)))
  1978.                                     {
  1979.                                         Msg -> Type = DATAMSGTYPE_CLEARBUFFER;
  1980.  
  1981.                                         UpdatePercent = TRUE;
  1982.  
  1983.                                         LT_LockWindow(BufferInfo -> Window);
  1984.  
  1985.                                         if(MsgQualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1986.                                         {
  1987.                                             PutMsgItem(SpecialQueue,(struct MsgItem *)Msg);
  1988.                                             Msg = NULL;
  1989.                                         }
  1990.                                         else
  1991.                                         {
  1992.                                             if(Config -> MiscConfig -> ProtectiveMode)
  1993.                                             {
  1994.                                                 if(!MyEasyRequest(BufferInfo -> Window,LocaleString(MSG_TERMBUFFER_BUFFER_STILL_HOLDS_LINES_TXT),LocaleString(MSG_GLOBAL_YES_NO_TXT),Lines))
  1995.                                                 {
  1996.                                                     LT_UnlockWindow(BufferInfo -> Window);
  1997.  
  1998.                                                     break;
  1999.                                                 }
  2000.                                             }
  2001.  
  2002.                                             PutMsgItem(SpecialQueue,(struct MsgItem *)Msg);
  2003.                                             Msg = NULL;
  2004.                                         }
  2005.  
  2006.                                         DeleteMsgItem(Msg);
  2007.                                     }
  2008.  
  2009.                                     LT_UnlockWindow(BufferInfo -> Window);
  2010.  
  2011.                                     FlushMsg(BufferInfo -> Window);
  2012.                                 }
  2013.  
  2014.                                 break;
  2015.                         }
  2016.  
  2017.                         MsgCode = MenuItem -> NextSelect;
  2018.                     }
  2019.                     else
  2020.                         break;
  2021.                 }
  2022.             }
  2023.  
  2024.         }
  2025.     }
  2026.  
  2027.     if(Context)
  2028.         DeleteSearchContext(Context);
  2029.  
  2030.     if(SearchInfo)
  2031.         DeleteSearchInfo(SearchInfo);
  2032.  
  2033.         // Put the stuff back
  2034.  
  2035.     *BufferInfo -> pTopLine            = BufferInfo -> TopLine;
  2036.     *BufferInfo -> pSearchForward    = BufferInfo -> SearchForward;
  2037.     *BufferInfo -> pIgnoreCase        = BufferInfo -> IgnoreCase;
  2038.     *BufferInfo -> pWholeWords        = BufferInfo -> WholeWords;
  2039.  
  2040.     return(RingBack);
  2041. }
  2042.  
  2043. STATIC VOID __regargs
  2044. DeleteBufferInfo(TextBufferInfo *BufferInfo)
  2045. {
  2046.     if(BufferInfo)
  2047.     {
  2048.         FreeVecPooled(BufferInfo -> BufferLineWidths);
  2049.  
  2050.         if(BufferInfo -> Window)
  2051.         {
  2052.             ClearMenuStrip(BufferInfo -> Window);
  2053.  
  2054.             LT_DeleteWindowLock(BufferInfo -> Window);
  2055.  
  2056.             CloseWindow(BufferInfo -> Window);
  2057.         }
  2058.  
  2059.         if(BufferInfo -> Scroller)
  2060.             DeleteScroller(BufferInfo);
  2061.  
  2062.         if(BufferInfo -> BufferAmigaGlyph)
  2063.             DisposeObject(BufferInfo -> BufferAmigaGlyph);
  2064.  
  2065.         if(BufferInfo -> BufferCheckGlyph)
  2066.             DisposeObject(BufferInfo -> BufferCheckGlyph);
  2067.  
  2068.         if(BufferInfo -> BufferDrawInfo)
  2069.             FreeScreenDrawInfo(BufferInfo -> Screen,BufferInfo -> BufferDrawInfo);
  2070.  
  2071.         if(BufferInfo -> BufferMenuStrip)
  2072.             LT_DisposeMenu(BufferInfo -> BufferMenuStrip);
  2073.  
  2074.         if(BufferInfo -> Screen && !BufferInfo -> Parent)
  2075.             CloseScreen(BufferInfo -> Screen);
  2076.  
  2077.         if(BufferInfo -> LocalFont)
  2078.             CloseFont(BufferInfo -> LocalFont);
  2079.  
  2080.         if(BufferInfo -> BufferSignal != -1)
  2081.             FreeSignal(BufferInfo -> BufferSignal);
  2082.  
  2083.         if(BufferInfo -> Queue)
  2084.             DeleteMsgQueue(BufferInfo -> Queue);
  2085.  
  2086.         FreeVecPooled(BufferInfo);
  2087.     }
  2088. }
  2089.  
  2090. STATIC TextBufferInfo * __regargs
  2091. CreateBufferInfo(struct Screen *Parent,BOOLEAN *pSearchForward,BOOLEAN *pIgnoreCase,BOOLEAN *pWholeWords,LONG *pTopLine)
  2092. {
  2093.     TextBufferInfo *BufferInfo;
  2094.  
  2095.     if(BufferInfo = (TextBufferInfo *)AllocVecPooled(sizeof(TextBufferInfo),MEMF_ANY | MEMF_CLEAR))
  2096.     {
  2097.         BOOLEAN                     Defaults;
  2098.  
  2099.         struct ColorSpec         ColorSpec[3];
  2100.  
  2101.         LONG                     Width,Height;
  2102.         ULONG                     DisplayMode;
  2103.  
  2104.         struct Rectangle         DisplayClip;
  2105.         struct DimensionInfo     DimensionInfo;
  2106.  
  2107.         BufferInfo -> pSearchForward    = pSearchForward;
  2108.         BufferInfo -> pIgnoreCase        = pIgnoreCase;
  2109.         BufferInfo -> pWholeWords        = pWholeWords;
  2110.         BufferInfo -> pTopLine            = pTopLine;
  2111.  
  2112.         BufferInfo -> TopLine        = *pTopLine;
  2113.         BufferInfo -> LastTopLine    = -1;
  2114.  
  2115.         BufferInfo -> SearchForward    = *pSearchForward;
  2116.         BufferInfo -> IgnoreCase    = *pIgnoreCase;
  2117.         BufferInfo -> WholeWords    = *pWholeWords;
  2118.  
  2119.         BufferInfo -> OldColumn        = -1;
  2120.         BufferInfo -> OldLine        = -1;
  2121.         BufferInfo -> OldLength        = -1;
  2122.  
  2123.         BufferInfo -> Buddy            = (struct Process *)FindTask(NULL);
  2124.  
  2125.         memcpy(&BufferInfo -> LocalTextFont,&TextFont,sizeof(struct TTextAttr));
  2126.  
  2127.         BufferInfo -> LocalTextFont . tta_Name    = BufferInfo -> LocalTextFontName;
  2128.         BufferInfo -> LocalTextFont . tta_YSize    = Config -> TerminalConfig -> TextFontHeight;
  2129.  
  2130.         strcpy(BufferInfo -> LocalTextFontName,Config -> TerminalConfig -> TextFontName);
  2131.  
  2132.         memcpy(&BufferInfo -> LocalUserFont,&UserFont,sizeof(struct TTextAttr));
  2133.  
  2134.         BufferInfo -> LocalUserFont . tta_Name = BufferInfo -> LocalUserFontName;
  2135.  
  2136.         strcpy(BufferInfo -> LocalUserFontName,UserFont . tta_Name);
  2137.  
  2138.         if(!Config -> CaptureConfig -> ConvertChars && Config -> TerminalConfig -> FontMode != FONT_STANDARD)
  2139.         {
  2140.             strcpy(BufferInfo -> LocalTextFontName,Config -> TerminalConfig -> IBMFontName);
  2141.  
  2142.             BufferInfo -> LocalTextFont . tta_YSize = Config -> TerminalConfig -> IBMFontHeight;
  2143.  
  2144.             BufferInfo -> NeedClipConversion = TRUE;
  2145.         }
  2146.         else
  2147.             BufferInfo -> NeedClipConversion = FALSE;
  2148.  
  2149.         if(BufferInfo -> LocalFont = OpenDiskFont(&BufferInfo -> LocalTextFont))
  2150.         {
  2151.             BufferInfo -> LocalTextFontBase        = BufferInfo -> LocalFont -> tf_Baseline;
  2152.             BufferInfo -> LocalTextFontWidth    = BufferInfo -> LocalFont -> tf_XSize;
  2153.             BufferInfo -> LocalTextFontHeight    = BufferInfo -> LocalFont -> tf_YSize;
  2154.  
  2155.             Forbid();
  2156.  
  2157.             if(Window && DrawInfo)
  2158.             {
  2159.                 UWORD Colour;
  2160.  
  2161.                     /* Set up the startup colours for our buffer screen. */
  2162.  
  2163.                 ColorSpec[0] . ColorIndex = 0;
  2164.  
  2165.                 Colour = GetRGB4(Window -> WScreen -> ViewPort . ColorMap,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  2166.  
  2167.                 ColorSpec[0] . Red        = (Colour >> 8) & 0xF;
  2168.                 ColorSpec[0] . Green    = (Colour >> 4) & 0xF;
  2169.                 ColorSpec[0] . Blue        = (Colour     ) & 0xF;
  2170.  
  2171.                 ColorSpec[1] . ColorIndex = 1;
  2172.  
  2173.                 Colour = GetRGB4(Window -> WScreen -> ViewPort . ColorMap,DrawInfo -> dri_Pens[TEXTPEN]);
  2174.  
  2175.                 ColorSpec[1] . Red        = (Colour >> 8) & 0xF;
  2176.                 ColorSpec[1] . Green    = (Colour >> 4) & 0xF;
  2177.                 ColorSpec[1] . Blue        = (Colour     ) & 0xF;
  2178.  
  2179.                 ColorSpec[2] . ColorIndex = -1;
  2180.  
  2181.                 Defaults = FALSE;
  2182.             }
  2183.             else
  2184.                 Defaults = TRUE;
  2185.  
  2186.             Permit();
  2187.  
  2188.             DisplayMode = Config -> CaptureConfig -> BufferScreenMode;
  2189.  
  2190.             if(ModeNotAvailable(DisplayMode))
  2191.                 DisplayMode = Config -> ScreenConfig -> DisplayMode;
  2192.  
  2193.             if(ModeNotAvailable(DisplayMode))
  2194.             {
  2195.                 struct Screen *PubScreen = LockPubScreen(NULL);
  2196.  
  2197.                 if(PubScreen)
  2198.                 {
  2199.                     DisplayMode = GetVPModeID(&PubScreen -> ViewPort);
  2200.  
  2201.                     UnlockPubScreen(NULL,PubScreen);
  2202.                 }
  2203.                 else
  2204.                     DisplayMode = DEFAULT_MONITOR_ID | HIRES_KEY;
  2205.             }
  2206.  
  2207.                 /* Set up the actual width of the screen we want. */
  2208.  
  2209.             Width = Config -> CaptureConfig -> BufferWidth * BufferInfo -> LocalTextFontWidth + BufferInfo -> ArrowWidth + 1;
  2210.  
  2211.             if((BufferInfo -> BufferSignal = AllocSignal(-1)) != -1)
  2212.             {
  2213.                     /* Get the mode dimension info. */
  2214.  
  2215.                 if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,DisplayMode))
  2216.                 {
  2217.                         /* Determine maximum text overscan width. */
  2218.  
  2219.                     LONG TextWidth = DimensionInfo . TxtOScan . MaxX - DimensionInfo . TxtOScan . MinX + 1;
  2220.  
  2221.                         /* Too small? */
  2222.  
  2223.                     if(Width < DimensionInfo . MinRasterWidth)
  2224.                         Width = DimensionInfo . MinRasterWidth;
  2225.  
  2226.                         /* Far too large? */
  2227.  
  2228.                     if(Width > DimensionInfo . MaxRasterWidth)
  2229.                         Width = DimensionInfo . MaxRasterWidth;
  2230.  
  2231.                         /* A bit too large? */
  2232.  
  2233.                     if(Width > TextWidth)
  2234.                         Width = TextWidth;
  2235.  
  2236.                         /* Inquire the text overscan dimensions. */
  2237.  
  2238.                     if(QueryOverscan(DisplayMode,&DisplayClip,OSCAN_TEXT))
  2239.                     {
  2240.                             /* Centre the buffer screen. */
  2241.  
  2242.                         if(DisplayClip . MaxX - DisplayClip . MinX + 1 > Width)
  2243.                         {
  2244.                             LONG Differ = (DisplayClip . MaxX - DisplayClip . MinX + 1 - Width) / 2;
  2245.  
  2246.                             switch(Config -> CaptureConfig -> BufferScreenPosition)
  2247.                             {
  2248.                                 case SCREEN_LEFT:
  2249.  
  2250.                                     DisplayClip . MaxX = DisplayClip . MinX + Width;
  2251.                                     break;
  2252.  
  2253.                                 case SCREEN_RIGHT:
  2254.  
  2255.                                     DisplayClip . MinX = DisplayClip . MaxX - Width;
  2256.                                     break;
  2257.  
  2258.                                 case SCREEN_CENTRE:
  2259.  
  2260.                                     DisplayClip . MinX += Differ;
  2261.                                     DisplayClip . MaxX -= Differ;
  2262.  
  2263.                                     break;
  2264.                             }
  2265.                         }
  2266.  
  2267.                             /* Open a single bitplane clone of the main screen. */
  2268.  
  2269.                         if(Parent)
  2270.                         {
  2271.                             BufferInfo -> Parent = Parent;
  2272.                             BufferInfo -> Screen = Parent;
  2273.  
  2274.                             if(BufferInfo -> Queue = CreateMsgQueue(NULL,0))
  2275.                                 BufferInfo -> QueueMask = BufferInfo -> Queue -> SigMask;
  2276.                             else
  2277.                                 BufferInfo -> Screen = NULL;
  2278.                         }
  2279.                         else
  2280.                         {
  2281.                             BufferInfo -> Screen = (struct Screen *)OpenScreenTags(NULL,
  2282.                                 SA_Title,        LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),
  2283.                                 SA_Depth,        1,
  2284.                                 SA_Left,        DisplayClip . MinX,
  2285.                                 SA_DClip,        &DisplayClip,
  2286.                                 SA_DisplayID,    DisplayMode,
  2287.                                 SA_Font,        &BufferInfo -> LocalUserFont,
  2288.                                 SA_Behind,        TRUE,
  2289.                                 SA_AutoScroll,    TRUE,
  2290.  
  2291.                                 Defaults ? TAG_IGNORE : SA_Colors,ColorSpec,
  2292.                             TAG_END);
  2293.                         }
  2294.  
  2295.                         if(BufferInfo -> Screen)
  2296.                         {
  2297.                             if(Parent)
  2298.                             {
  2299.                                 BufferInfo -> BufferMenuStrip = LT_NewMenuTags(
  2300.                                     LH_LocaleHook,    &LocaleHook,
  2301.                                     LAMN_Screen,    BufferInfo -> Screen,
  2302.                                     LAMN_TextAttr,    &BufferInfo -> LocalUserFont,
  2303.                                     AmigaGlyph ? LAMN_AmigaGlyph        : TAG_IGNORE, AmigaGlyph,
  2304.                                     CheckGlyph ? LAMN_CheckmarkGlyph    : TAG_IGNORE, CheckGlyph,
  2305.  
  2306.                                     LAMN_TitleID,    MSG_TERMREVIEW_PROJECT_MEN,
  2307.                                         LAMN_ItemID,    MSG_TERMREVIEW_SEARCH_MEN,
  2308.                                             LAMN_UserData,    MEN_SEARCH,
  2309.                                         LAMN_ItemID,    MSG_TERMREVIEW_REPEAT_SEARCH_MEN,
  2310.                                             LAMN_UserData,    MEN_REPEAT,
  2311.  
  2312.                                         LAMN_ItemText,    NM_BARLABEL,
  2313.  
  2314.                                         LAMN_ItemID,    MSG_TERMREVIEW_CLEAR_BUFFER_MEN,
  2315.                                             LAMN_UserData,    MEN_CLEARBUF_CONTENTS,
  2316.  
  2317.                                         LAMN_ItemText,    NM_BARLABEL,
  2318.  
  2319.                                         LAMN_ItemID,    MSG_TERMREVIEW_CLOSE_BUFFER_MEN,
  2320.                                             LAMN_UserData,    MEN_QUITBUF,
  2321.  
  2322.                                         LAMN_ItemID,    MSG_CLOSE_WINDOW_TXT,
  2323.                                             LAMN_KeyText,    ":",
  2324.                                             LAMN_UserData,    MEN_QUITBUF,
  2325.  
  2326.                                     LAMN_TitleID,    MSG_TERMBUFFER_EDIT_MEN,
  2327.                                         LAMN_ItemID,    MSG_TERMBUFFER_PASTE_MEN,
  2328.                                             LAMN_UserData,    MEN_PASTECLIP,
  2329.                                 TAG_DONE);
  2330.                             }
  2331.                             else
  2332.                             {
  2333.                                 BufferInfo -> BufferMenuStrip = LT_NewMenuTags(
  2334.                                     LH_LocaleHook,    &LocaleHook,
  2335.                                     LAMN_Screen,    BufferInfo -> Screen,
  2336.                                     LAMN_TextAttr,    &BufferInfo -> LocalUserFont,
  2337.                                     AmigaGlyph ? LAMN_AmigaGlyph        : TAG_IGNORE, AmigaGlyph,
  2338.                                     CheckGlyph ? LAMN_CheckmarkGlyph    : TAG_IGNORE, CheckGlyph,
  2339.  
  2340.                                     LAMN_TitleID,    MSG_TERMBUFFER_PROJECT_MEN,
  2341.                                         LAMN_ItemID,    MSG_TERMBUFFER_SEARCH_MEN,
  2342.                                             LAMN_UserData,    MEN_SEARCH,
  2343.                                         LAMN_ItemID,    MSG_TERMBUFFER_REPEAT_SEARCH_MEN,
  2344.                                             LAMN_UserData,    MEN_REPEAT,
  2345.  
  2346.                                         LAMN_ItemText,    NM_BARLABEL,
  2347.  
  2348.                                         LAMN_ItemID,    MSG_TERMBUFFER_GO_TO_MAIN_SCREEN_MEN,
  2349.                                             LAMN_UserData,    MEN_GOTO,
  2350.  
  2351.                                         LAMN_ItemText,    NM_BARLABEL,
  2352.  
  2353.                                         LAMN_ItemID,    MSG_TERMBUFFER_CLEAR_BUFFER_MEN,
  2354.                                             LAMN_UserData,    MEN_CLEARBUF_CONTENTS,
  2355.  
  2356.                                         LAMN_ItemText,    NM_BARLABEL,
  2357.  
  2358.                                         LAMN_ItemID,    MSG_TERMBUFFER_CLOSE_BUFFER_MEN,
  2359.                                             LAMN_UserData,    MEN_QUITBUF,
  2360.                                 TAG_DONE);
  2361.                             }
  2362.  
  2363.                             if(BufferInfo -> BufferMenuStrip)
  2364.                             {
  2365.                                 if(BufferInfo -> BufferDrawInfo = GetScreenDrawInfo(BufferInfo -> Screen))
  2366.                                 {
  2367.                                     if(BufferInfo -> BufferDrawInfo -> dri_NumPens > BARDETAILPEN)
  2368.                                     {
  2369.                                         BufferInfo -> TitleFrontPen    = BufferInfo -> BufferDrawInfo -> dri_Pens[BARDETAILPEN];
  2370.                                         BufferInfo -> TitleBackPen    = BufferInfo -> BufferDrawInfo -> dri_Pens[BARBLOCKPEN];
  2371.                                     }
  2372.                                     else
  2373.                                     {
  2374.                                         BufferInfo -> TitleFrontPen    = BufferInfo -> BufferDrawInfo -> dri_Pens[DETAILPEN];
  2375.                                         BufferInfo -> TitleBackPen    = BufferInfo -> BufferDrawInfo -> dri_Pens[BLOCKPEN];
  2376.                                     }
  2377.  
  2378.                                     BufferInfo -> TextFrontPen    = BufferInfo -> BufferDrawInfo -> dri_Pens[TEXTPEN];
  2379.                                     BufferInfo -> TextBackPen    = BufferInfo -> BufferDrawInfo -> dri_Pens[BACKGROUNDPEN];
  2380.  
  2381.                                     if(!CreateMenuGlyphs(BufferInfo -> Screen,BufferInfo -> BufferDrawInfo,&BufferInfo -> BufferAmigaGlyph,&BufferInfo -> BufferCheckGlyph))
  2382.                                     {
  2383.                                         BufferInfo -> BufferAmigaGlyph    = NULL;
  2384.                                         BufferInfo -> BufferCheckGlyph    = NULL;
  2385.                                     }
  2386.  
  2387.                                     BufferInfo -> MaxPen = MAX(BufferInfo -> TextFrontPen,BufferInfo -> TextBackPen);
  2388.  
  2389.                                     Height = (BufferInfo -> Screen -> Height - (BufferInfo -> Screen -> BarHeight + 2)) / BufferInfo -> LocalTextFontHeight;
  2390.  
  2391.                                     if(CreateScroller(BufferInfo,Height * BufferInfo -> LocalTextFontHeight))
  2392.                                     {
  2393.                                         if(BufferInfo -> Window = OpenWindowTags(NULL,
  2394.                                             WA_Top,                Parent ? Window -> TopEdge + Window -> BorderTop : BufferInfo -> Screen -> BarHeight + 2,
  2395.                                             WA_Left,            Parent ? Window -> LeftEdge : 0,
  2396.                                             WA_Width,            Parent ? Window -> Width : BufferInfo -> Screen -> Width,
  2397.                                             WA_Height,            Parent ? Window -> Height - Window -> BorderTop : Height * BufferInfo -> LocalTextFontHeight,
  2398.                                             WA_Backdrop,        Parent == NULL,
  2399.                                             WA_Borderless,        Parent == NULL,
  2400.                                             WA_DepthGadget,        Parent != NULL,
  2401.                                             WA_DragBar,            Parent != NULL,
  2402.                                             WA_CloseGadget,        Parent != NULL,
  2403.                                             WA_SizeGadget,        Parent != NULL,
  2404.                                             WA_NoCareRefresh,    TRUE,
  2405.                                             WA_CustomScreen,    BufferInfo -> Screen,
  2406.                                             WA_NewLookMenus,    TRUE,
  2407.                                             WA_RptQueue,        1,
  2408.                                             WA_IDCMP,            IDCMP_IDCMPUPDATE | IDCMP_RAWKEY | IDCMP_INACTIVEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MOUSEBUTTONS | IDCMP_MENUPICK | IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE | IDCMP_MENUHELP | IDCMP_SIZEVERIFY | IDCMP_NEWSIZE | IDCMP_CLOSEWINDOW,
  2409.                                             WA_MenuHelp,        TRUE,
  2410.                                             WA_Gadgets,            BufferInfo -> Scroller,
  2411.                                             BackfillTag,        Parent ? &BackfillHook : NULL,
  2412.  
  2413.                                             BufferInfo -> BufferAmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, BufferInfo -> BufferAmigaGlyph,
  2414.                                             BufferInfo -> BufferCheckGlyph ? WA_Checkmark : TAG_IGNORE, BufferInfo -> BufferCheckGlyph,
  2415.                                         TAG_DONE))
  2416.                                         {
  2417.                                             SetMenuStrip(BufferInfo -> Window,BufferInfo -> BufferMenuStrip);
  2418.  
  2419.                                             BufferInfo -> Left        = BufferInfo -> Window -> BorderLeft;
  2420.                                             BufferInfo -> Top        = BufferInfo -> Window -> BorderTop;
  2421.                                             BufferInfo -> Width        = BufferInfo -> Window -> Width        - (BufferInfo -> Window -> BorderLeft    + BufferInfo -> Window -> BorderRight);
  2422.                                             BufferInfo -> Height    = BufferInfo -> Window -> Height    - (BufferInfo -> Window -> BorderTop    + BufferInfo -> Window -> BorderBottom);
  2423.  
  2424.                                             if(Parent)
  2425.                                             {
  2426.                                                 BufferInfo -> Width        -= BufferInfo -> Width    % BufferInfo -> LocalTextFontWidth;
  2427.                                                 BufferInfo -> Height    -= BufferInfo -> Height    % BufferInfo -> LocalTextFontHeight;
  2428.  
  2429.                                                 WindowLimits(BufferInfo -> Window,BufferInfo -> Window -> BorderLeft + 20 * BufferInfo -> LocalTextFontWidth + BufferInfo -> Window -> BorderRight,BufferInfo -> Window -> BorderTop + BufferInfo -> LocalTextFontHeight + BufferInfo -> Window -> BorderBottom,BufferInfo -> Screen -> Width,BufferInfo -> Screen -> Height);
  2430.                                             }
  2431.                                             else
  2432.                                                 BufferInfo -> Width -= BufferInfo -> ArrowWidth;
  2433.  
  2434.                                             if(BufferInfo -> BufferLineWidths = (UWORD *)AllocVecPooled(2 * sizeof(UWORD) * (BufferInfo -> Window -> WScreen -> Height / BufferInfo -> LocalTextFontHeight + 1) + sizeof(UWORD) * (BufferInfo -> Window -> WScreen -> Width / BufferInfo -> LocalTextFontWidth + 1),MEMF_ANY | MEMF_CLEAR))
  2435.                                             {
  2436.                                                 UWORD    Index;
  2437.                                                 WORD    i;
  2438.  
  2439.                                                 BufferInfo -> BufferLineOffsets        = &BufferInfo -> BufferLineWidths[BufferInfo -> Window -> WScreen -> Height / BufferInfo -> LocalTextFontHeight + 1];
  2440.                                                 BufferInfo -> BufferColumnOffsets    = &BufferInfo -> BufferLineOffsets[BufferInfo -> Window -> WScreen -> Height / BufferInfo -> LocalTextFontHeight + 1];
  2441.  
  2442.                                                 for(i = Index = 0 ; i < BufferInfo -> Window -> WScreen -> Height / BufferInfo -> LocalTextFontHeight + 1 ; i++)
  2443.                                                 {
  2444.                                                     BufferInfo -> BufferLineOffsets[i] = Index;
  2445.  
  2446.                                                     Index += BufferInfo -> LocalTextFontHeight;
  2447.                                                 }
  2448.  
  2449.                                                 for(i = Index = 0 ; i < BufferInfo -> Window -> WScreen -> Width / BufferInfo -> LocalTextFontWidth + 1 ; i++)
  2450.                                                 {
  2451.                                                     BufferInfo -> BufferColumnOffsets[i] = Index;
  2452.  
  2453.                                                     Index += BufferInfo -> LocalTextFontWidth;
  2454.                                                 }
  2455.  
  2456.                                                     /* Determine maximum dimensions of
  2457.                                                      * the buffer screen (in rows and
  2458.                                                      * columns).
  2459.                                                      */
  2460.  
  2461.                                                 if(Parent)
  2462.                                                     BufferInfo -> NumBufferColumns = BufferInfo -> Width / BufferInfo -> LocalTextFontWidth;
  2463.                                                 else
  2464.                                                     BufferInfo -> NumBufferColumns = (BufferInfo -> Window -> Width - (BufferInfo -> ArrowWidth + 1)) / BufferInfo -> LocalTextFontWidth;
  2465.  
  2466.                                                 BufferInfo -> NumBufferLines = BufferInfo -> Height / BufferInfo -> LocalTextFontHeight;
  2467.  
  2468.                                                 if(BufferInfo -> TopLine == -1 || !Config -> CaptureConfig -> RememberBufferScreen)
  2469.                                                 {
  2470.                                                     switch(Config -> CaptureConfig -> OpenBufferScreen)
  2471.                                                     {
  2472.                                                         case BUFFER_TOP:
  2473.  
  2474.                                                             BufferInfo -> TopLine = 0;
  2475.                                                             break;
  2476.  
  2477.                                                         case BUFFER_END:
  2478.  
  2479.                                                             if((BufferInfo -> TopLine = Lines - BufferInfo -> NumBufferLines) < 0)
  2480.                                                                 BufferInfo -> TopLine = 0;
  2481.  
  2482.                                                             break;
  2483.  
  2484.                                                         default:
  2485.  
  2486.                                                             BufferInfo -> TopLine = 0;
  2487.                                                             break;
  2488.                                                     }
  2489.                                                 }
  2490.  
  2491.                                                 if(BufferInfo -> TopLine > Lines - BufferInfo -> NumBufferLines || BufferInfo -> TopLine < 0)
  2492.                                                     BufferInfo -> TopLine = 0;
  2493.  
  2494.                                                 BufferInfo -> RPort = BufferInfo -> Window -> RPort;
  2495.  
  2496.                                                 SetFont(BufferInfo -> RPort,BufferInfo -> LocalFont);
  2497.  
  2498.                                                     /* Bring the screen to the front. */
  2499.  
  2500.                                                 BumpWindow(BufferInfo -> Window);
  2501.  
  2502.                                                     /* Set the drawing pens for the window. */
  2503.  
  2504.                                                 if(Kick30)
  2505.                                                 {
  2506.                                                     SetABPenDrMd(BufferInfo -> RPort,BufferInfo -> TextFrontPen,BufferInfo -> TextBackPen,JAM2);
  2507.                                                     SetMaxPen(BufferInfo -> RPort,BufferInfo -> MaxPen);
  2508.                                                 }
  2509.                                                 else
  2510.                                                 {
  2511.                                                     SetAPen(BufferInfo -> RPort,BufferInfo -> TextFrontPen);
  2512.                                                     SetBPen(BufferInfo -> RPort,BufferInfo -> TextBackPen);
  2513.                                                     SetDrMd(BufferInfo -> RPort,JAM2);
  2514.                                                 }
  2515.  
  2516.                                                     /* Initial creation of the buffer display. */
  2517.  
  2518.                                                 BufferInfo -> DisplayedLines = RedrawScreen(BufferInfo,BufferInfo -> TopLine);
  2519.  
  2520.                                                 SetGadgetAttrs(BufferInfo -> Scroller,BufferInfo -> Window,NULL,
  2521.                                                     PGA_Top,        BufferInfo -> TopLine,
  2522.                                                     PGA_Total,        Lines,
  2523.                                                     PGA_Visible,    BufferInfo -> NumBufferLines,
  2524.                                                 TAG_DONE);
  2525.  
  2526.                                                 BufferInfo -> TitleOffset = TextLength(BufferInfo -> Screen -> BarLayer -> rp,LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),strlen(LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT))) + TextLength(BufferInfo -> Screen -> BarLayer -> rp,"  ",1) + 4;
  2527.  
  2528.                                                 return(BufferInfo);
  2529.                                             }
  2530.                                         }
  2531.                                     }
  2532.                                 }
  2533.                             }
  2534.                         }
  2535.                     }
  2536.                 }
  2537.             }
  2538.         }
  2539.     }
  2540.  
  2541.     DeleteBufferInfo(BufferInfo);
  2542.  
  2543.     return(NULL);
  2544. }
  2545.  
  2546.     /* BufferServer():
  2547.      *
  2548.      *    Asynchronous task to display the data stored in the
  2549.      *    scrollback display buffer.
  2550.      */
  2551.  
  2552. STATIC VOID __saveds
  2553. BufferServer(VOID)
  2554. {
  2555.     STATIC BOOLEAN    SearchForward    = TRUE,
  2556.                     IgnoreCase        = TRUE,
  2557.                     WholeWords        = FALSE;
  2558.     STATIC LONG        TopLine            = -1;
  2559.  
  2560.     TextBufferInfo    *BufferInfo;
  2561.     struct Task        *Father;
  2562.     BOOLEAN             RingBack = TRUE;
  2563.  
  2564.         // Wake this guy up
  2565.  
  2566.     Father = (struct Task *)SysBase -> ThisTask -> tc_UserData;
  2567.  
  2568.         // Snap our fingers...
  2569.  
  2570.     if(BufferInfo = CreateBufferInfo(NULL,&SearchForward,&IgnoreCase,&WholeWords,&TopLine))
  2571.     {
  2572.             // Open wide, here I come!
  2573.  
  2574.         ObtainSemaphore(&BufferTaskSemaphore);
  2575.  
  2576.         BufferInfoData = BufferInfo;
  2577.  
  2578.         ReleaseSemaphore(&BufferTaskSemaphore);
  2579.  
  2580.             // Up and running
  2581.  
  2582.         Signal(Father,SIG_HANDSHAKE);
  2583.  
  2584.         Father = NULL;
  2585.  
  2586.             // Swish the tinsel
  2587.  
  2588.         RingBack = HandleBuffer(&BufferTaskSemaphore,&BufferInfoData);
  2589.  
  2590.             // Activate the main window again
  2591.  
  2592.         if(Window)
  2593.             BumpWindow(Window);
  2594.  
  2595.             // The wrecking crew
  2596.  
  2597.         DeleteBufferInfo(BufferInfo);
  2598.     }
  2599.  
  2600.         // Shutdown in an orderly fashion
  2601.  
  2602.     Forbid();
  2603.  
  2604.     if(RingBack)
  2605.     {
  2606.         if(Father)
  2607.             Signal(Father,SIG_HANDSHAKE);
  2608.         else
  2609.             Signal(ThisProcess,SIG_HANDSHAKE);
  2610.     }
  2611. }
  2612.  
  2613.     /* LaunchBuffer():
  2614.      *
  2615.      *    Launch the buffer process.
  2616.      */
  2617.  
  2618. BYTE
  2619. LaunchBuffer()
  2620. {
  2621.     ObtainSemaphore(&BufferTaskSemaphore);
  2622.  
  2623.         /* Is the buffer process already running? */
  2624.  
  2625.     if(BufferInfoData)
  2626.     {
  2627.             /* Tell it to bring its screen to the front. */
  2628.  
  2629.         Signal(BufferInfoData -> Buddy,SIG_TOFRONT);
  2630.  
  2631.         ReleaseSemaphore(&BufferTaskSemaphore);
  2632.  
  2633.             /* Return success. */
  2634.  
  2635.         return(TRUE);
  2636.     }
  2637.     else
  2638.     {
  2639.         struct Task    *Child;
  2640.         BYTE         Result = FALSE;
  2641.  
  2642.         ReleaseSemaphore(&BufferTaskSemaphore);
  2643.  
  2644.         Forbid();
  2645.  
  2646.             /* Launch the buffer process. */
  2647.  
  2648.         if(Child = (struct Task *)CreateNewProcTags(
  2649.             NP_Entry,        BufferServer,
  2650.             NP_Name,        "term Buffer Process",
  2651.             NP_Priority,    SysBase -> ThisTask -> tc_Node . ln_Pri,
  2652.             NP_StackSize,    4000,
  2653.             NP_WindowPtr,    -1,
  2654.         TAG_END))
  2655.         {
  2656.             Child -> tc_UserData = SysBase -> ThisTask;
  2657.  
  2658.             ClrSignal(SIG_HANDSHAKE);
  2659.  
  2660.             Wait(SIG_HANDSHAKE);
  2661.  
  2662.             ObtainSemaphore(&BufferTaskSemaphore);
  2663.  
  2664.             if(BufferInfoData)
  2665.                 Result = TRUE;
  2666.  
  2667.             ReleaseSemaphore(&BufferTaskSemaphore);
  2668.         }
  2669.  
  2670.         Permit();
  2671.  
  2672.             /* Return the result. */
  2673.  
  2674.         return(Result);
  2675.     }
  2676. }
  2677.  
  2678.     /* TerminateBuffer():
  2679.      *
  2680.      *    Terminate the buffer process.
  2681.      */
  2682.  
  2683. VOID
  2684. TerminateBuffer()
  2685. {
  2686.     ObtainSemaphore(&BufferTaskSemaphore);
  2687.  
  2688.     if(BufferInfoData)
  2689.     {
  2690.         Forbid();
  2691.  
  2692.         Signal(BufferInfoData -> Buddy,SIG_KILL);
  2693.  
  2694.         ReleaseSemaphore(&BufferTaskSemaphore);
  2695.  
  2696.         ClrSignal(SIG_HANDSHAKE);
  2697.  
  2698.         Wait(SIG_HANDSHAKE);
  2699.  
  2700.         Permit();
  2701.     }
  2702.     else
  2703.         ReleaseSemaphore(&BufferTaskSemaphore);
  2704. }
  2705.  
  2706.     /* MoveBuffer(TextBufferInfo *BufferInfo,BYTE Mode):
  2707.      *
  2708.      *    Move the currently displayed buffer area somewhere.
  2709.      */
  2710.  
  2711. VOID __regargs
  2712. MoveBuffer(struct SignalSemaphore *Access,const struct TextBufferInfo **Data,BYTE Mode)
  2713. {
  2714.     struct TextBufferInfo *BufferInfo;
  2715.  
  2716.     ObtainSemaphore(Access);
  2717.  
  2718.     BufferInfo = (TextBufferInfo *)*Data;
  2719.  
  2720.     if(BufferInfo && BufferInfo -> Queue)
  2721.     {
  2722.         BYTE SigBit;
  2723.  
  2724.         if((SigBit = AllocSignal(-1)) != -1)
  2725.         {
  2726.             struct DataMsg Msg;
  2727.  
  2728.             InitMsgItem(&Msg,BufferDestructor);
  2729.  
  2730.             Msg . Type        = DATAMSGTYPE_MOVEREVIEW;
  2731.             Msg . Size        = Mode;
  2732.             Msg . Client    = SysBase -> ThisTask;
  2733.             Msg . Mask        = 1L << SigBit;
  2734.  
  2735.             ClrSignal(Msg . Mask);
  2736.  
  2737.             PutMsgItem(BufferInfo -> Queue,(struct MsgItem *)&Msg);
  2738.  
  2739.             ReleaseSemaphore(Access);
  2740.  
  2741.             Wait(Msg . Mask);
  2742.  
  2743.             FreeSignal(SigBit);
  2744.  
  2745.             return;
  2746.         }
  2747.     }
  2748.  
  2749.     ReleaseSemaphore(Access);
  2750. }
  2751.  
  2752.     /* NotifyBuffer(struct SignalSemaphore *Access,const struct TextBufferInfo **Data,ULONG Signals):
  2753.      *
  2754.      *    Send a signal to the buffer process.
  2755.      */
  2756.  
  2757. VOID __regargs
  2758. NotifyBuffer(struct SignalSemaphore *Access,const struct TextBufferInfo **Data,ULONG Signals)
  2759. {
  2760.     struct TextBufferInfo *BufferInfo;
  2761.  
  2762.     ObtainSemaphore(Access);
  2763.  
  2764.     BufferInfo = (TextBufferInfo *)*Data;
  2765.  
  2766.     if(BufferInfo && BufferInfo -> Buddy)
  2767.     {
  2768.         Forbid();
  2769.  
  2770.         ReleaseSemaphore(Access);
  2771.  
  2772.         ClrSignal(SIG_HANDSHAKE);
  2773.  
  2774.         Signal(BufferInfo -> Buddy,Signals);
  2775.  
  2776.         Wait(SIG_HANDSHAKE);
  2777.  
  2778.         Permit();
  2779.     }
  2780.     else
  2781.         ReleaseSemaphore(Access);
  2782. }
  2783.  
  2784.  
  2785. /*****************************************************************************/
  2786.  
  2787.  
  2788. STATIC VOID __saveds
  2789. ReviewServer(VOID)
  2790. {
  2791.     STATIC BOOLEAN    SearchForward    = TRUE,
  2792.                     IgnoreCase        = TRUE,
  2793.                     WholeWords        = FALSE;
  2794.     STATIC LONG        TopLine            = -1;
  2795.  
  2796.     TextBufferInfo    *BufferInfo;
  2797.     struct Task        *Father;
  2798.     BOOLEAN             RingBack = TRUE;
  2799.  
  2800.         // Wake this guy up
  2801.  
  2802.     Father = (struct Task *)SysBase -> ThisTask -> tc_UserData;
  2803.  
  2804.         // Snap our fingers...
  2805.  
  2806.     if(BufferInfo = CreateBufferInfo(Window -> WScreen,&SearchForward,&IgnoreCase,&WholeWords,&TopLine))
  2807.     {
  2808.             // Open wide, here I come!
  2809.  
  2810.         ObtainSemaphore(&ReviewTaskSemaphore);
  2811.  
  2812.         ReviewInfoData = BufferInfo;
  2813.  
  2814.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2815.  
  2816.             // Up and running
  2817.  
  2818.         Signal(Father,SIG_HANDSHAKE);
  2819.  
  2820.         Father = NULL;
  2821.  
  2822.             // Swish the tinsel
  2823.  
  2824.         RingBack = HandleBuffer(&ReviewTaskSemaphore,&ReviewInfoData);
  2825.  
  2826.             // Activate the main window again
  2827.  
  2828.         if(Window)
  2829.             BumpWindow(Window);
  2830.  
  2831.             // The wrecking crew
  2832.  
  2833.         DeleteBufferInfo(BufferInfo);
  2834.  
  2835.         Forbid();
  2836.  
  2837.         CheckItem(MEN_REVIEW_WINDOW,FALSE);
  2838.  
  2839.         Permit();
  2840.     }
  2841.  
  2842.         // Shutdown in an orderly fashion
  2843.  
  2844.     Forbid();
  2845.  
  2846.     if(RingBack)
  2847.     {
  2848.         if(Father)
  2849.             Signal(Father,SIG_HANDSHAKE);
  2850.         else
  2851.             Signal(ThisProcess,SIG_HANDSHAKE);
  2852.     }
  2853. }
  2854.  
  2855. VOID __regargs
  2856. MoveReview(BYTE Mode)
  2857. {
  2858.     MoveBuffer(&ReviewTaskSemaphore,&ReviewInfoData,Mode);
  2859. }
  2860.  
  2861. VOID
  2862. DeleteReview()
  2863. {
  2864.     CheckItem(MEN_REVIEW_WINDOW,FALSE);
  2865.  
  2866.     ObtainSemaphore(&ReviewTaskSemaphore);
  2867.  
  2868.     if(ReviewInfoData)
  2869.     {
  2870.         Forbid();
  2871.  
  2872.         Signal(ReviewInfoData -> Buddy,SIG_KILL);
  2873.  
  2874.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2875.  
  2876.         ClrSignal(SIG_HANDSHAKE);
  2877.  
  2878.         Wait(SIG_HANDSHAKE);
  2879.  
  2880.         Permit();
  2881.     }
  2882.     else
  2883.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2884. }
  2885.  
  2886. BYTE
  2887. CreateReview()
  2888. {
  2889.     BYTE Result = FALSE;
  2890.  
  2891.     ObtainSemaphore(&ReviewTaskSemaphore);
  2892.  
  2893.         /* Is the Review process already running? */
  2894.  
  2895.     if(ReviewInfoData)
  2896.     {
  2897.             /* Tell it to bring its screen to the front. */
  2898.  
  2899.         Signal(ReviewInfoData -> Buddy,SIG_TOFRONT);
  2900.  
  2901.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2902.  
  2903.             /* Return success. */
  2904.  
  2905.         Result = TRUE;
  2906.     }
  2907.     else
  2908.     {
  2909.         struct Task    *Child;
  2910.  
  2911.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2912.  
  2913.         Forbid();
  2914.  
  2915.             /* Launch the Review process. */
  2916.  
  2917.         if(Child = (struct Task *)CreateNewProcTags(
  2918.             NP_Entry,        ReviewServer,
  2919.             NP_Name,        "term Review Process",
  2920.             NP_Priority,    SysBase -> ThisTask -> tc_Node . ln_Pri,
  2921.             NP_StackSize,    4000,
  2922.             NP_WindowPtr,    -1,
  2923.         TAG_END))
  2924.         {
  2925.             Child -> tc_UserData = SysBase -> ThisTask;
  2926.  
  2927.             ClrSignal(SIG_HANDSHAKE);
  2928.  
  2929.             Wait(SIG_HANDSHAKE);
  2930.  
  2931.             ObtainSemaphore(&ReviewTaskSemaphore);
  2932.  
  2933.             if(ReviewInfoData)
  2934.                 Result = TRUE;
  2935.  
  2936.             ReleaseSemaphore(&ReviewTaskSemaphore);
  2937.         }
  2938.  
  2939.         Permit();
  2940.     }
  2941.  
  2942.     if(Result)
  2943.         CheckItem(MEN_REVIEW_WINDOW,TRUE);
  2944.  
  2945.     return(Result);
  2946. }
  2947.